From 5b99a5335fc259cc1eb89f469c79f6fa38ff849b Mon Sep 17 00:00:00 2001 From: wesrer Date: Wed, 6 May 2020 13:42:34 +0530 Subject: [PATCH 1/2] refactoring I have so far - cut out into separate file --- Cargo.lock | 95 + Cargo.toml | 2 + parity/cli/args.rs | 1266 ++++++++++ parity/cli/config.rs | 17 + parity/cli/config/config_default.toml | 151 ++ parity/cli/config/config_dev.toml | 158 ++ parity/cli/config/config_dev_insecure.toml | 158 ++ parity/cli/config/config_insecure.toml | 157 ++ parity/cli/config/config_mining.toml | 182 ++ .../cli/config/config_non_standard_ports.toml | 160 ++ parity/cli/config/test_config.toml | 80 + parity/cli/globals.rs | 1177 +++++++++ parity/cli/mod.rs | 2202 +---------------- parity/cli/parse_cli.rs | 12 + parity/cli/presets/config.dev-insecure.toml | 12 - parity/cli/presets/config.dev.toml | 6 - parity/cli/presets/config.insecure.toml | 7 - parity/cli/presets/config.mining.toml | 32 - .../presets/config.non-standard-ports.toml | 7 - parity/cli/presets/mod.rs | 28 - parity/cli/subcommands.rs | 223 ++ parity/cli/tests/config.full.toml | 172 -- parity/cli/tests/config.invalid1.toml | 2 - parity/cli/tests/config.invalid2.toml | 4 - parity/cli/tests/config.invalid3.toml | 3 - parity/cli/tests/config.invalid4.toml | 2 - parity/cli/tests/config.stratum_disabled.toml | 2 - parity/cli/tests/config.stratum_enabled.toml | 5 - .../tests/config.stratum_missing_field.toml | 1 - .../tests/config.stratum_missing_section.toml | 1 - parity/cli/tests/config.toml | 90 - parity/cli/tests/mod.rs | 2 + parity/cli/tests/test_cli.rs | 61 + parity/cli/usage.rs | 774 ------ parity/configuration.rs | 953 +------ parity/deprecated.rs | 305 --- parity/lib.rs | 18 +- parity/main.rs | 3 +- parity/test_configuration.rs | 1147 +++++++++ 39 files changed, 5134 insertions(+), 4543 deletions(-) create mode 100644 parity/cli/args.rs create mode 100644 parity/cli/config.rs create mode 100644 parity/cli/config/config_default.toml create mode 100644 parity/cli/config/config_dev.toml create mode 100644 parity/cli/config/config_dev_insecure.toml create mode 100644 parity/cli/config/config_insecure.toml create mode 100644 parity/cli/config/config_mining.toml create mode 100644 parity/cli/config/config_non_standard_ports.toml create mode 100644 parity/cli/config/test_config.toml create mode 100644 parity/cli/globals.rs create mode 100644 parity/cli/parse_cli.rs delete mode 100644 parity/cli/presets/config.dev-insecure.toml delete mode 100644 parity/cli/presets/config.dev.toml delete mode 100644 parity/cli/presets/config.insecure.toml delete mode 100644 parity/cli/presets/config.mining.toml delete mode 100644 parity/cli/presets/config.non-standard-ports.toml delete mode 100644 parity/cli/presets/mod.rs create mode 100644 parity/cli/subcommands.rs delete mode 100644 parity/cli/tests/config.full.toml delete mode 100644 parity/cli/tests/config.invalid1.toml delete mode 100644 parity/cli/tests/config.invalid2.toml delete mode 100644 parity/cli/tests/config.invalid3.toml delete mode 100644 parity/cli/tests/config.invalid4.toml delete mode 100644 parity/cli/tests/config.stratum_disabled.toml delete mode 100644 parity/cli/tests/config.stratum_enabled.toml delete mode 100644 parity/cli/tests/config.stratum_missing_field.toml delete mode 100644 parity/cli/tests/config.stratum_missing_section.toml delete mode 100644 parity/cli/tests/config.toml create mode 100644 parity/cli/tests/mod.rs create mode 100644 parity/cli/tests/test_cli.rs delete mode 100644 parity/cli/usage.rs delete mode 100644 parity/deprecated.rs create mode 100644 parity/test_configuration.rs diff --git a/Cargo.lock b/Cargo.lock index 022e1c0b328..c2aba399cc3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3167,6 +3167,7 @@ dependencies = [ "registrar", "rlp", "rpassword", + "rust-embed", "rustc-hex 2.1.0", "rustc_version", "semver", @@ -3175,6 +3176,7 @@ dependencies = [ "serde_json", "snapshot", "spec", + "structopt", "tempfile", "term_size", "textwrap", @@ -3838,6 +3840,32 @@ dependencies = [ "toml", ] +[[package]] +name = "proc-macro-error" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98e9e4b82e0ef281812565ea4751049f1bdcdfccda7d3f459f2e138a40c08678" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2 1.0.9", + "quote 1.0.3", + "syn 1.0.17", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f5444ead4e9935abd7f27dc51f7e852a0569ac888096d5ec2499470794e2e53" +dependencies = [ + "proc-macro2 1.0.9", + "quote 1.0.3", + "syn 1.0.17", + "syn-mid", + "version_check", +] + [[package]] name = "proc-macro-hack" version = "0.5.14" @@ -4265,6 +4293,38 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b386f4748bdae2aefc96857f5fda07647f851d089420e577831e2a14b45230f8" +[[package]] +name = "rust-embed" +version = "5.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a17890cbd0fae97c2006fa1ecec9554946443c319f4dd8cd8d3b92031725161" +dependencies = [ + "rust-embed-impl", + "rust-embed-utils", + "walkdir", +] + +[[package]] +name = "rust-embed-impl" +version = "5.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60cacc306d294556771c6e92737ba7e6be0264144bc46dd713a14ef384b0d6b8" +dependencies = [ + "quote 1.0.3", + "rust-embed-utils", + "syn 1.0.17", + "walkdir", +] + +[[package]] +name = "rust-embed-utils" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97655158074ccb2d2cfb1ccb4c956ef0f4054e43a2c1e71146d4991e6961e105" +dependencies = [ + "walkdir", +] + [[package]] name = "rustc-demangle" version = "0.1.16" @@ -4765,6 +4825,30 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" +[[package]] +name = "structopt" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "863246aaf5ddd0d6928dfeb1a9ca65f505599e4e1b399935ef7e75107516b4ef" +dependencies = [ + "clap", + "lazy_static", + "structopt-derive", +] + +[[package]] +name = "structopt-derive" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d239ca4b13aee7a2142e6795cbd69e457665ff8037aed33b3effdc430d2f927a" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2 1.0.9", + "quote 1.0.3", + "syn 1.0.17", +] + [[package]] name = "subtle" version = "1.0.0" @@ -4799,6 +4883,17 @@ dependencies = [ "unicode-xid 0.2.0", ] +[[package]] +name = "syn-mid" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a" +dependencies = [ + "proc-macro2 1.0.9", + "quote 1.0.3", + "syn 1.0.17", +] + [[package]] name = "synstructure" version = "0.12.3" diff --git a/Cargo.toml b/Cargo.toml index fe140117de1..19915db40c2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -75,9 +75,11 @@ serde_derive = "1.0" serde_json = "1.0" snapshot = { path = "ethcore/snapshot" } spec = { path = "ethcore/spec" } +structopt = "~0.3" term_size = "0.3" textwrap = "0.11.0" toml = "0.5.6" +rust-embed = "5.5.1" verification = { path = "ethcore/verification" } [build-dependencies] diff --git a/parity/cli/args.rs b/parity/cli/args.rs new file mode 100644 index 00000000000..1401c034509 --- /dev/null +++ b/parity/cli/args.rs @@ -0,0 +1,1266 @@ +use cli::config::get_config; +use cli::globals::{Globals, IPCOptions}; +use cli::parse_cli::*; +use cli::subcommands::*; +use std::fs; +use structopt::StructOpt; + +#[derive(Debug, PartialEq)] +pub enum ArgsError { + ConfigParseError(String), + ConfigReadError(String), + ConfigWriteError(String), + PeerConfigurationError(String), +} + +#[derive(Default, Debug, PartialEq, Clone)] +pub struct Args { + pub cmd_daemon: bool, + pub arg_daemon_pid_file: Option, + + pub cmd_account: bool, + pub cmd_account_new: bool, + pub cmd_account_list: bool, + pub cmd_account_import: bool, + pub arg_account_import_path: Option>, + + pub cmd_wallet: bool, + pub cmd_wallet_import: bool, + pub arg_wallet_import_path: Option, + + pub cmd_import: bool, + pub arg_import_format: Option, + pub arg_import_file: Option, + + pub cmd_export: bool, + pub cmd_export_blocks: bool, + pub arg_export_blocks_format: Option, + pub arg_export_blocks_from: String, + pub arg_export_blocks_to: String, + pub arg_export_blocks_file: Option, + + pub cmd_export_state: bool, + pub flag_export_state_no_storage: bool, + pub flag_export_state_no_code: bool, + pub arg_export_state_min_balance: Option, + pub arg_export_state_max_balance: Option, + pub arg_export_state_at: String, + pub arg_export_state_format: Option, + pub arg_export_state_file: Option, + + pub cmd_signer: bool, + pub cmd_signer_new_token: bool, + pub cmd_signer_list: bool, + pub cmd_signer_sign: bool, + pub arg_signer_sign_id: Option, + pub cmd_signer_reject: bool, + pub arg_signer_reject_id: Option, + + pub cmd_snapshot: bool, + pub arg_snapshot_at: String, + pub arg_snapshot_file: Option, + + pub cmd_restore: bool, + pub arg_restore_file: Option, + + pub cmd_tools: bool, + pub cmd_tools_hash: bool, + pub arg_tools_hash_file: Option, + + pub cmd_db: bool, + pub cmd_db_kill: bool, + pub cmd_db_reset: bool, + pub arg_db_reset_num: u32, + + pub cmd_export_hardcoded_sync: bool, + + pub cmd_dapp: bool, + pub arg_dapp_path: Option, + + pub flag_no_download: bool, + pub flag_no_consensus: bool, + pub flag_light: bool, + pub flag_no_hardcoded_sync: bool, + pub flag_force_direct: bool, + pub arg_mode: String, + pub arg_mode_timeout: u64, + pub arg_mode_alarm: u64, + pub arg_auto_update: String, + pub arg_auto_update_delay: u16, + pub arg_auto_update_check_frequency: u16, + pub arg_release_track: String, + pub arg_chain: String, + pub arg_keys_path: String, + pub arg_identity: String, + pub arg_base_path: Option, + pub arg_db_path: Option, + pub arg_sync_until: Option, + pub flag_unsafe_expose: bool, + pub arg_config: String, + pub arg_ports_shift: u16, + pub flag_fast_unlock: bool, + pub arg_keys_iterations: u32, + pub arg_accounts_refresh: u64, + pub arg_unlock: Option, + pub arg_enable_signing_queue: bool, + pub arg_password: Vec, + pub flag_private_enabled: bool, + pub flag_private_state_offchain: bool, + pub arg_private_signer: Option, + pub arg_private_validators: Option, + pub arg_private_account: Option, + pub arg_private_sstore_url: Option, + pub arg_private_sstore_threshold: Option, + pub arg_private_passwords: Option, + pub arg_ui_path: String, + pub flag_no_warp: bool, + pub flag_no_discovery: bool, + pub flag_reserved_only: bool, + pub flag_no_ancient_blocks: bool, + pub flag_no_serve_light: bool, + pub arg_warp_barrier: Option, + pub arg_port: u16, + pub arg_interface: String, + pub arg_min_peers: Option, + pub arg_max_peers: Option, + pub arg_snapshot_peers: u16, + pub arg_nat: String, + pub arg_allow_ips: String, + pub arg_max_pending_peers: u16, + pub arg_network_id: Option, + pub arg_bootnodes: Option, + pub arg_node_key: Option, + pub arg_reserved_peers: Option, + pub flag_jsonrpc_allow_missing_blocks: bool, + pub flag_no_jsonrpc: bool, + pub flag_jsonrpc_no_keep_alive: bool, + pub flag_jsonrpc_experimental: bool, + pub arg_jsonrpc_port: u16, + pub arg_jsonrpc_interface: String, + pub arg_jsonrpc_apis: String, + pub arg_jsonrpc_hosts: String, + pub arg_jsonrpc_server_threads: Option, + pub arg_jsonrpc_cors: String, + pub arg_jsonrpc_max_payload: Option, + pub arg_poll_lifetime: u32, + pub flag_no_ws: bool, + pub arg_ws_port: u16, + pub arg_ws_interface: String, + pub arg_ws_apis: String, + pub arg_ws_origins: String, + pub arg_ws_hosts: String, + pub arg_ws_max_connections: usize, + pub flag_no_ipc: bool, + pub arg_ipc_path: String, + pub arg_ipc_chmod: String, + pub arg_ipc_apis: String, + pub arg_on_demand_response_time_window: Option, + pub arg_on_demand_request_backoff_start: Option, + pub arg_on_demand_request_backoff_max: Option, + pub arg_on_demand_request_backoff_rounds_max: Option, + pub arg_on_demand_request_consecutive_failures: Option, + pub flag_no_secretstore: bool, + pub flag_no_secretstore_http: bool, + pub flag_no_secretstore_auto_migrate: bool, + pub arg_secretstore_http_cors: String, + pub arg_secretstore_acl_contract: Option, + pub arg_secretstore_contract: Option, + pub arg_secretstore_srv_gen_contract: Option, + pub arg_secretstore_srv_retr_contract: Option, + pub arg_secretstore_doc_store_contract: Option, + pub arg_secretstore_doc_sretr_contract: Option, + pub arg_secretstore_nodes: String, + pub arg_secretstore_server_set_contract: Option, + pub arg_secretstore_interface: String, + pub arg_secretstore_port: u16, + pub arg_secretstore_http_interface: String, + pub arg_secretstore_http_port: u16, + pub arg_secretstore_path: String, + pub arg_secretstore_secret: Option, + pub arg_secretstore_admin_public: Option, + pub flag_force_sealing: bool, + pub flag_reseal_on_uncle: bool, + pub flag_remove_solved: bool, + pub flag_tx_queue_no_unfamiliar_locals: bool, + pub flag_tx_queue_no_early_reject: bool, + pub flag_refuse_service_transactions: bool, + pub flag_infinite_pending_block: bool, + pub flag_no_persistent_txqueue: bool, + pub flag_stratum: bool, + pub arg_reseal_on_txs: String, + pub arg_reseal_min_period: u64, + pub arg_reseal_max_period: u64, + pub arg_work_queue_size: usize, + pub arg_relay_set: String, + pub arg_usd_per_tx: String, + pub arg_usd_per_eth: String, + pub arg_price_update_period: String, + pub arg_gas_floor_target: String, + pub arg_gas_cap: String, + pub arg_tx_queue_mem_limit: u32, + pub arg_tx_queue_size: usize, + pub arg_tx_queue_per_sender: Option, + pub arg_tx_queue_locals: Option, + pub arg_tx_queue_strategy: String, + pub arg_stratum_interface: String, + pub arg_stratum_port: u16, + pub arg_min_gas_price: Option, + pub arg_gas_price_percentile: usize, + pub arg_author: Option, + pub arg_engine_signer: Option, + pub arg_tx_gas_limit: Option, + pub arg_tx_time_limit: Option, + pub arg_extra_data: Option, + pub arg_notify_work: Option, + pub arg_stratum_secret: Option, + pub arg_max_round_blocks_to_import: usize, + pub flag_can_restart: bool, + pub flag_no_color: bool, + // NOTE: This is auto handled by structopt + // pub flag_version: bool, + pub flag_no_config: bool, + pub arg_logging: Option, + pub arg_log_file: Option, + pub flag_scale_verifiers: bool, + pub arg_tracing: String, + pub arg_pruning: String, + pub arg_pruning_history: u64, + pub arg_pruning_memory: usize, + pub arg_cache_size_db: u32, + pub arg_cache_size_blocks: u32, + pub arg_cache_size_queue: u32, + pub arg_cache_size_state: u32, + pub arg_db_compaction: String, + pub arg_fat_db: String, + pub arg_cache_size: Option, + pub arg_num_verifiers: Option, + pub flag_no_seal_check: bool, + pub flag_no_periodic_snapshot: bool, + pub arg_snapshot_threads: Option, + pub flag_whisper: bool, + pub arg_whisper_pool_size: Option, + pub flag_geth: bool, + pub flag_import_geth_keys: bool, +} + +impl Args { + pub fn parse() -> Result { + let mut args: Args = Default::default(); + + let mut raw_input = ArgsInput::from_args(); + + Args::save_current_config(&mut raw_input.globals)?; + + // This is the hardcoded config provided by openethereum, with + // no special presets + // FIXME: convert this to relative pathing + let fallback_config_path = "config_default.toml"; + + let default_config_path = match &raw_input.globals.convenience.config { + // the has given a custom configuration + Some(x) => { + match x.as_str() { + // presets + "dev" => "config_dev.toml", + "dev-insecure" => "config_dev_insecure.toml", + "insecure" => "config_insecure.toml", + "mining" => "config_mining.toml", + "non-standard-ports" => "config_non_standard_ports.toml", + + // user given config path + _ => x, + } + } + + // no input options for configuration + None => { + // We can make the default and the fallback the same + "config_default.toml" + } + }; + + let (default_config, fallback_config) = + Args::generate_default_configuration(default_config_path, fallback_config_path)?; + + args.absorb_cli(raw_input, default_config, fallback_config)?; + + Ok(args) + } + + pub fn save_current_config(globals: &mut Globals) -> Result<(), ArgsError> { + // We don't want to print the config generate option on the generated toml, so we + // reset it + let config_generate = globals.convenience.config_generate.clone(); + globals.convenience.config_generate = None; + + if let Some(path) = &config_generate { + let current_flags = toml::to_string(globals).map_err(|e| { + ArgsError::ConfigWriteError(format!( + "Failed to generate valid config toml from current flags: {}.Please report a bug if this error persists.", e + )) + })?; + + fs::write(&path, current_flags).map_err(|_| { + ArgsError::ConfigParseError(format!( + "Failed to write config to given file path {}. Please try again with a valid path and config name.", &path + )) + })?; + } + Ok(()) + } + + pub fn generate_default_configuration( + default_config_path: &str, + fallback_config_path: &str, + ) -> Result<(Globals, Globals), ArgsError> { + // FIXME: throw an error when file is not found + let default_config_file:String = get_config(default_config_path)?; + let fallback_config_file:String = get_config(fallback_config_path)?; + + let default_config: Globals = toml::from_str(&default_config_file).map_err(|e| { + ArgsError::ConfigParseError(format!( + "Failure to parse config file: {}, error: {}", + default_config_path, e + )) + })?; + + let fallback_config: Globals = toml::from_str(&fallback_config_file).map_err(|e| { + ArgsError::ConfigParseError(format!( + "Failure to parse config file {}: {}", + fallback_config_path, e + )) + })?; + + Ok((default_config, fallback_config)) + } + + pub fn absorb_cli( + &mut self, + cli_args: ArgsInput, + default_globals: Globals, + fallback_globals: Globals, + ) -> Result<(), ArgsError> { + self.absorb_subcommands(&cli_args)?; + self.absorb_globals(cli_args, default_globals, fallback_globals)?; + Ok(()) + } + + fn absorb_subcommands(&mut self, cli_args: &ArgsInput) -> Result<(), ArgsError> { + match &cli_args.subcommands { + None => {} + Some(subcommand) => match &subcommand { + SubCommands::Daemon(d) => { + self.cmd_daemon = true; + + self.arg_daemon_pid_file = d.pid_file.clone(); + } + SubCommands::Wallet { wallet } => { + self.cmd_wallet = true; + + let Wallet::Import { path } = wallet; + self.cmd_wallet_import = true; + self.arg_wallet_import_path = (*path).clone(); + } + SubCommands::Account { account } => { + self.cmd_account = true; + + match account { + Account::New => { + self.cmd_account_new = true; + } + Account::Import { path } => { + self.cmd_account_import = true; + self.arg_account_import_path = Some((*path).clone()); + } + Account::List => { + self.cmd_account_list = true; + } + } + } + SubCommands::Import(i) => { + self.cmd_import = true; + self.arg_import_format = i.format.clone(); + self.arg_import_file = i.file.clone(); + } + SubCommands::Export { export } => { + self.cmd_export = true; + match export { + Export::Blocks(eb) => { + self.cmd_export_blocks = true; + self.arg_export_blocks_format = eb.format.clone(); + self.arg_export_blocks_from = eb.from.clone(); + self.arg_export_blocks_to = eb.to.clone(); + self.arg_export_blocks_file = eb.file.clone(); + } + Export::State(es) => { + self.cmd_export_state = true; + self.flag_export_state_no_storage = es.no_storage; + self.flag_export_state_no_code = es.no_code; + self.arg_export_state_min_balance = es.min_balance.clone(); + self.arg_export_state_max_balance = es.max_balance.clone(); + self.arg_export_state_at = es.at.clone(); + self.arg_export_state_format = es.format.clone(); + self.arg_export_state_file = es.file.clone(); + } + } + } + SubCommands::Signer(s) => { + self.cmd_signer = true; + match s { + Signer::NewToken => { + self.cmd_signer_new_token = true; + } + Signer::List => { + self.cmd_signer_list = true; + } + Signer::Sign { id } => { + self.cmd_signer_sign = true; + self.arg_signer_sign_id = *id; + } + Signer::Reject { id } => { + self.cmd_signer_reject = true; + self.arg_signer_reject_id = *id; + } + } + } + SubCommands::Restore(r) => { + self.cmd_restore = true; + self.arg_restore_file = r.file.clone(); + } + SubCommands::Snapshots(s) => { + self.cmd_snapshot = true; + self.arg_snapshot_at = s.at.clone(); + self.arg_snapshot_file = s.file.clone(); + } + SubCommands::Db(db) => { + self.cmd_db = true; + match db { + Db::Kill => { + self.cmd_db_kill = true; + } + Db::Reset { num } => { + self.cmd_db_reset = true; + self.arg_db_reset_num = *num; + } + } + } + SubCommands::ExportHardcodedSync => { + self.cmd_export_hardcoded_sync = true; + } + + }, + } + Ok(()) + } + + fn select_value(raw: Option, default: Option, fallback: Option) -> T { + raw.or(default).or(fallback).expect("Value is always present, at least in fallback") + } + + fn select_option(raw: Option, default: Option, fallback: Option) -> Option { + raw.or(default).or(fallback) + } + + fn absorb_globals( + &mut self, + cli_args: ArgsInput, + defaults: Globals, + fallback: Globals, + ) -> Result<(), ArgsError> { + self.absorb_global_flags(&cli_args, &defaults, &fallback); + self.absorb_global_options(cli_args, defaults, fallback); + + if let (Some(min_peers), Some(max_peers)) = (self.arg_min_peers, self.arg_max_peers) { + if max_peers < min_peers { + return Err(ArgsError::PeerConfigurationError( + "max-peers need to be greater than or equal to min-peers".to_owned(), + )); + } + } + Ok(()) + } + + fn absorb_global_options(&mut self, cli_args: ArgsInput, defaults: Globals, fallback: Globals) { + // Unnatural cases + + self.arg_ipc_path = Args::select_value( + cli_args.globals.ipc.ipc_path, + Some(IPCOptions::ipc_path_default()), + None, // We don't care about fallback in this case, since the previous operation is infallible + ); + self.arg_password = cli_args.globals.account.password; + + self.arg_config = Args::select_value( + cli_args.globals.convenience.config, + defaults.convenience.config, + fallback.convenience.config, + ); + self.arg_ports_shift = Args::select_value( + cli_args.globals.convenience.ports_shift, + defaults.convenience.ports_shift, + fallback.convenience.ports_shift, + ); + self.arg_keys_iterations = Args::select_value( + cli_args.globals.account.keys_iterations, + defaults.account.keys_iterations, + fallback.account.keys_iterations, + ); + self.arg_accounts_refresh = Args::select_value( + cli_args.globals.account.accounts_refresh, + defaults.account.accounts_refresh, + fallback.account.accounts_refresh, + ); + self.arg_unlock = Args::select_option( + cli_args.globals.account.unlock, + defaults.account.unlock, + fallback.account.unlock, + ); + self.arg_db_path = Args::select_option( + cli_args.globals.operating.db_path, + defaults.operating.db_path, + fallback.operating.db_path, + ); + self.arg_sync_until = Args::select_option( + cli_args.globals.operating.sync_until, + defaults.operating.sync_until, + fallback.operating.sync_until, + ); + self.arg_mode = Args::select_value( + cli_args.globals.operating.mode, + defaults.operating.mode, + fallback.operating.mode, + ); + self.arg_mode_timeout = Args::select_value( + cli_args.globals.operating.mode_timeout, + defaults.operating.mode_timeout, + fallback.operating.mode_timeout, + ); + self.arg_mode_alarm = Args::select_value( + cli_args.globals.operating.mode_alarm, + defaults.operating.mode_alarm, + fallback.operating.mode_alarm, + ); + self.arg_auto_update = Args::select_value( + cli_args.globals.operating.auto_update, + defaults.operating.auto_update, + fallback.operating.auto_update, + ); + self.arg_auto_update_delay = Args::select_value( + cli_args.globals.operating.auto_update_delay, + defaults.operating.auto_update_delay, + fallback.operating.auto_update_delay, + ); + self.arg_auto_update_check_frequency = Args::select_value( + cli_args.globals.operating.auto_update_check_frequency, + defaults.operating.auto_update_check_frequency, + fallback.operating.auto_update_check_frequency, + ); + self.arg_release_track = Args::select_value( + cli_args.globals.operating.release_track, + defaults.operating.release_track, + fallback.operating.release_track, + ); + self.arg_chain = Args::select_value( + cli_args.globals.operating.chain, + defaults.operating.chain, + fallback.operating.chain, + ); + self.arg_keys_path = Args::select_value( + cli_args.globals.operating.keys_path, + defaults.operating.keys_path, + fallback.operating.keys_path, + ); + self.arg_identity = Args::select_value( + cli_args.globals.operating.identity, + defaults.operating.identity, + fallback.operating.identity, + ); + self.arg_base_path = Args::select_option( + cli_args.globals.operating.base_path, + defaults.operating.base_path, + fallback.operating.base_path, + ); + self.arg_private_validators = Args::select_option( + cli_args.globals.private_transactions.private_validators, + defaults.private_transactions.private_validators, + fallback.private_transactions.private_validators, + ); + self.arg_private_account = Args::select_option( + cli_args.globals.private_transactions.private_account, + defaults.private_transactions.private_account, + fallback.private_transactions.private_account, + ); + self.arg_private_sstore_url = Args::select_option( + cli_args.globals.private_transactions.private_sstore_url, + defaults.private_transactions.private_sstore_url, + fallback.private_transactions.private_sstore_url, + ); + self.arg_private_sstore_threshold = Args::select_option( + cli_args + .globals + .private_transactions + .private_sstore_threshold, + defaults.private_transactions.private_sstore_threshold, + fallback.private_transactions.private_sstore_threshold, + ); + self.arg_private_passwords = Args::select_option( + cli_args.globals.private_transactions.private_passwords, + defaults.private_transactions.private_passwords, + fallback.private_transactions.private_passwords, + ); + self.arg_ui_path = Args::select_value( + cli_args.globals.ui_options.ui_path, + defaults.ui_options.ui_path, + fallback.ui_options.ui_path, + ); + self.arg_warp_barrier = Args::select_option( + cli_args.globals.networking.warp_barrier, + defaults.networking.warp_barrier, + fallback.networking.warp_barrier, + ); + self.arg_port = Args::select_value( + cli_args.globals.networking.port, + defaults.networking.port, + fallback.networking.port, + ); + self.arg_interface = Args::select_value( + cli_args.globals.networking.interface, + defaults.networking.interface, + fallback.networking.interface, + ); + self.arg_min_peers = Args::select_option( + cli_args.globals.networking.min_peers, + defaults.networking.min_peers, + fallback.networking.min_peers, + ); + self.arg_max_peers = Args::select_option( + cli_args.globals.networking.max_peers, + defaults.networking.max_peers, + fallback.networking.max_peers, + ); + self.arg_snapshot_peers = Args::select_value( + cli_args.globals.networking.snapshot_peers, + defaults.networking.snapshot_peers, + fallback.networking.snapshot_peers, + ); + self.arg_nat = Args::select_value( + cli_args.globals.networking.nat, + defaults.networking.nat, + fallback.networking.nat, + ); + self.arg_allow_ips = Args::select_value( + cli_args.globals.networking.allow_ips, + defaults.networking.allow_ips, + fallback.networking.allow_ips, + ); + self.arg_max_pending_peers = Args::select_value( + cli_args.globals.networking.max_pending_peers, + defaults.networking.max_pending_peers, + fallback.networking.max_pending_peers, + ); + self.arg_network_id = Args::select_option( + cli_args.globals.networking.network_id, + defaults.networking.network_id, + fallback.networking.network_id, + ); + self.arg_bootnodes = Args::select_option( + cli_args.globals.networking.bootnodes, + defaults.networking.bootnodes, + fallback.networking.bootnodes, + ); + self.arg_node_key = Args::select_option( + cli_args.globals.networking.node_key, + defaults.networking.node_key, + fallback.networking.node_key, + ); + self.arg_reserved_peers = Args::select_option( + cli_args.globals.networking.reserved_peers, + defaults.networking.reserved_peers, + fallback.networking.reserved_peers, + ); + self.arg_jsonrpc_port = Args::select_value( + cli_args.globals.http_json_rpc.jsonrpc_port, + defaults.http_json_rpc.jsonrpc_port, + fallback.http_json_rpc.jsonrpc_port, + ); + self.arg_jsonrpc_interface = Args::select_value( + cli_args.globals.http_json_rpc.jsonrpc_interface, + defaults.http_json_rpc.jsonrpc_interface, + fallback.http_json_rpc.jsonrpc_interface, + ); + self.arg_jsonrpc_apis = Args::select_value( + cli_args.globals.http_json_rpc.jsonrpc_apis, + defaults.http_json_rpc.jsonrpc_apis, + fallback.http_json_rpc.jsonrpc_apis, + ); + self.arg_jsonrpc_hosts = Args::select_value( + cli_args.globals.http_json_rpc.jsonrpc_hosts, + defaults.http_json_rpc.jsonrpc_hosts, + fallback.http_json_rpc.jsonrpc_hosts, + ); + self.arg_jsonrpc_server_threads = Args::select_option( + cli_args.globals.http_json_rpc.jsonrpc_server_threads, + defaults.http_json_rpc.jsonrpc_server_threads, + fallback.http_json_rpc.jsonrpc_server_threads, + ); + self.arg_jsonrpc_cors = Args::select_value( + cli_args.globals.http_json_rpc.jsonrpc_cors, + defaults.http_json_rpc.jsonrpc_cors, + fallback.http_json_rpc.jsonrpc_cors, + ); + self.arg_jsonrpc_max_payload = Args::select_option( + cli_args.globals.http_json_rpc.jsonrpc_max_payload, + defaults.http_json_rpc.jsonrpc_max_payload, + fallback.http_json_rpc.jsonrpc_max_payload, + ); + self.arg_poll_lifetime = Args::select_value( + cli_args.globals.http_json_rpc.poll_lifetime, + defaults.http_json_rpc.poll_lifetime, + fallback.http_json_rpc.poll_lifetime, + ); + self.arg_ws_port = Args::select_value( + cli_args.globals.websockets.ws_port, + defaults.websockets.ws_port, + fallback.websockets.ws_port, + ); + self.arg_ws_interface = Args::select_value( + cli_args.globals.websockets.ws_interface, + defaults.websockets.ws_interface, + fallback.websockets.ws_interface, + ); + self.arg_ws_apis = Args::select_value( + cli_args.globals.websockets.ws_apis, + defaults.websockets.ws_apis, + fallback.websockets.ws_apis, + ); + self.arg_ws_origins = Args::select_value( + cli_args.globals.websockets.ws_origins, + defaults.websockets.ws_origins, + fallback.websockets.ws_origins, + ); + self.arg_ws_hosts = Args::select_value( + cli_args.globals.websockets.ws_hosts, + defaults.websockets.ws_hosts, + fallback.websockets.ws_hosts, + ); + self.arg_ws_max_connections = Args::select_value( + cli_args.globals.websockets.ws_max_connections, + defaults.websockets.ws_max_connections, + fallback.websockets.ws_max_connections, + ); + self.arg_ipc_chmod = Args::select_value( + cli_args.globals.ipc.ipc_chmod, + defaults.ipc.ipc_chmod, + fallback.ipc.ipc_chmod, + ); + self.arg_ipc_apis = Args::select_value( + cli_args.globals.ipc.ipc_apis, + defaults.ipc.ipc_apis, + fallback.ipc.ipc_apis, + ); + self.arg_on_demand_response_time_window = Args::select_option( + cli_args.globals.light_client.on_demand_response_time_window, + defaults.light_client.on_demand_response_time_window, + fallback.light_client.on_demand_response_time_window, + ); + self.arg_secretstore_http_cors = Args::select_value( + cli_args.globals.secret_store.secretstore_http_cors, + defaults.secret_store.secretstore_http_cors, + fallback.secret_store.secretstore_http_cors, + ); + self.arg_secretstore_acl_contract = Args::select_option( + cli_args.globals.secret_store.secretstore_acl_contract, + defaults.secret_store.secretstore_acl_contract, + fallback.secret_store.secretstore_acl_contract, + ); + self.arg_secretstore_contract = Args::select_option( + cli_args.globals.secret_store.secretstore_contract, + defaults.secret_store.secretstore_contract, + fallback.secret_store.secretstore_contract, + ); + self.arg_secretstore_interface = Args::select_value( + cli_args.globals.secret_store.secretstore_interface, + defaults.secret_store.secretstore_interface, + fallback.secret_store.secretstore_interface, + ); + self.arg_secretstore_port = Args::select_value( + cli_args.globals.secret_store.secretstore_port, + defaults.secret_store.secretstore_port, + fallback.secret_store.secretstore_port, + ); + self.arg_secretstore_http_port = Args::select_value( + cli_args.globals.secret_store.secretstore_http_port, + defaults.secret_store.secretstore_http_port, + fallback.secret_store.secretstore_http_port, + ); + self.arg_secretstore_path = Args::select_value( + cli_args.globals.secret_store.secretstore_path, + defaults.secret_store.secretstore_path, + fallback.secret_store.secretstore_path, + ); + self.arg_secretstore_secret = Args::select_option( + cli_args.globals.secret_store.secretstore_secret, + defaults.secret_store.secretstore_secret, + fallback.secret_store.secretstore_secret, + ); + self.arg_secretstore_admin_public = Args::select_option( + cli_args.globals.secret_store.secretstore_admin_public, + defaults.secret_store.secretstore_admin_public, + fallback.secret_store.secretstore_admin_public, + ); + self.arg_reseal_on_txs = Args::select_value( + cli_args.globals.sealing_mining.reseal_on_txs, + defaults.sealing_mining.reseal_on_txs, + fallback.sealing_mining.reseal_on_txs, + ); + self.arg_reseal_min_period = Args::select_value( + cli_args.globals.sealing_mining.reseal_min_period, + defaults.sealing_mining.reseal_min_period, + fallback.sealing_mining.reseal_min_period, + ); + self.arg_reseal_max_period = Args::select_value( + cli_args.globals.sealing_mining.reseal_max_period, + defaults.sealing_mining.reseal_max_period, + fallback.sealing_mining.reseal_max_period, + ); + self.arg_work_queue_size = Args::select_value( + cli_args.globals.sealing_mining.work_queue_size, + defaults.sealing_mining.work_queue_size, + fallback.sealing_mining.work_queue_size, + ); + self.arg_relay_set = Args::select_value( + cli_args.globals.sealing_mining.relay_set, + defaults.sealing_mining.relay_set, + fallback.sealing_mining.relay_set, + ); + self.arg_usd_per_tx = Args::select_value( + cli_args.globals.sealing_mining.usd_per_tx, + defaults.sealing_mining.usd_per_tx, + fallback.sealing_mining.usd_per_tx, + ); + self.arg_usd_per_eth = Args::select_value( + cli_args.globals.sealing_mining.usd_per_eth, + defaults.sealing_mining.usd_per_eth, + fallback.sealing_mining.usd_per_eth, + ); + self.arg_price_update_period = Args::select_value( + cli_args.globals.sealing_mining.price_update_period, + defaults.sealing_mining.price_update_period, + fallback.sealing_mining.price_update_period, + ); + self.arg_gas_floor_target = Args::select_value( + cli_args.globals.sealing_mining.gas_floor_target, + defaults.sealing_mining.gas_floor_target, + fallback.sealing_mining.gas_floor_target, + ); + self.arg_gas_cap = Args::select_value( + cli_args.globals.sealing_mining.gas_cap, + defaults.sealing_mining.gas_cap, + fallback.sealing_mining.gas_cap, + ); + self.arg_tx_queue_mem_limit = Args::select_value( + cli_args.globals.sealing_mining.tx_queue_mem_limit, + defaults.sealing_mining.tx_queue_mem_limit, + fallback.sealing_mining.tx_queue_mem_limit, + ); + self.arg_tx_queue_size = Args::select_value( + cli_args.globals.sealing_mining.tx_queue_size, + defaults.sealing_mining.tx_queue_size, + fallback.sealing_mining.tx_queue_size, + ); + self.arg_tx_queue_per_sender = Args::select_option( + cli_args.globals.sealing_mining.tx_queue_per_sender, + defaults.sealing_mining.tx_queue_per_sender, + fallback.sealing_mining.tx_queue_per_sender, + ); + self.arg_tx_queue_locals = Args::select_option( + cli_args.globals.sealing_mining.tx_queue_locals, + defaults.sealing_mining.tx_queue_locals, + fallback.sealing_mining.tx_queue_locals, + ); + self.arg_tx_queue_strategy = Args::select_value( + cli_args.globals.sealing_mining.tx_queue_strategy, + defaults.sealing_mining.tx_queue_strategy, + fallback.sealing_mining.tx_queue_strategy, + ); + self.arg_stratum_interface = Args::select_value( + cli_args.globals.sealing_mining.stratum_interface, + defaults.sealing_mining.stratum_interface, + fallback.sealing_mining.stratum_interface, + ); + self.arg_stratum_port = Args::select_value( + cli_args.globals.sealing_mining.stratum_port, + defaults.sealing_mining.stratum_port, + fallback.sealing_mining.stratum_port, + ); + self.arg_min_gas_price = Args::select_option( + cli_args.globals.sealing_mining.min_gas_price, + defaults.sealing_mining.min_gas_price, + fallback.sealing_mining.min_gas_price, + ); + self.arg_gas_price_percentile = Args::select_value( + cli_args.globals.sealing_mining.gas_price_percentile, + defaults.sealing_mining.gas_price_percentile, + fallback.sealing_mining.gas_price_percentile, + ); + self.arg_author = Args::select_option( + cli_args.globals.sealing_mining.author, + defaults.sealing_mining.author, + fallback.sealing_mining.author, + ); + self.arg_engine_signer = Args::select_option( + cli_args.globals.sealing_mining.engine_signer, + defaults.sealing_mining.engine_signer, + fallback.sealing_mining.engine_signer, + ); + self.arg_tx_gas_limit = Args::select_option( + cli_args.globals.sealing_mining.tx_gas_limit, + defaults.sealing_mining.tx_gas_limit, + fallback.sealing_mining.tx_gas_limit, + ); + self.arg_tx_time_limit = Args::select_option( + cli_args.globals.sealing_mining.tx_time_limit, + defaults.sealing_mining.tx_time_limit, + fallback.sealing_mining.tx_time_limit, + ); + self.arg_extra_data = Args::select_option( + cli_args.globals.sealing_mining.extra_data, + defaults.sealing_mining.extra_data, + fallback.sealing_mining.extra_data, + ); + self.arg_notify_work = Args::select_option( + cli_args.globals.sealing_mining.notify_work, + defaults.sealing_mining.notify_work, + fallback.sealing_mining.notify_work, + ); + self.arg_stratum_secret = Args::select_option( + cli_args.globals.sealing_mining.stratum_secret, + defaults.sealing_mining.stratum_secret, + fallback.sealing_mining.stratum_secret, + ); + self.arg_logging = Args::select_option( + cli_args.globals.miscellaneous.logging, + defaults.miscellaneous.logging, + fallback.miscellaneous.logging, + ); + self.arg_log_file = Args::select_option( + cli_args.globals.miscellaneous.log_file, + defaults.miscellaneous.log_file, + fallback.miscellaneous.log_file, + ); + self.arg_tracing = Args::select_value( + cli_args.globals.footprint.tracing, + defaults.footprint.tracing, + fallback.footprint.tracing, + ); + self.arg_pruning = Args::select_value( + cli_args.globals.footprint.pruning, + defaults.footprint.pruning, + fallback.footprint.pruning, + ); + self.arg_pruning_history = Args::select_value( + cli_args.globals.footprint.pruning_history, + defaults.footprint.pruning_history, + fallback.footprint.pruning_history, + ); + self.arg_pruning_memory = Args::select_value( + cli_args.globals.footprint.pruning_memory, + defaults.footprint.pruning_memory, + fallback.footprint.pruning_memory, + ); + self.arg_cache_size_db = Args::select_value( + cli_args.globals.footprint.cache_size_db, + defaults.footprint.cache_size_db, + fallback.footprint.cache_size_db, + ); + self.arg_cache_size_blocks = Args::select_value( + cli_args.globals.footprint.cache_size_blocks, + defaults.footprint.cache_size_blocks, + fallback.footprint.cache_size_blocks, + ); + self.arg_cache_size_queue = Args::select_value( + cli_args.globals.footprint.cache_size_queue, + defaults.footprint.cache_size_queue, + fallback.footprint.cache_size_queue, + ); + self.arg_cache_size_state = Args::select_value( + cli_args.globals.footprint.cache_size_state, + defaults.footprint.cache_size_state, + fallback.footprint.cache_size_state, + ); + self.arg_db_compaction = Args::select_value( + cli_args.globals.footprint.db_compaction, + defaults.footprint.db_compaction, + fallback.footprint.db_compaction, + ); + self.arg_fat_db = Args::select_value( + cli_args.globals.footprint.fat_db, + defaults.footprint.fat_db, + fallback.footprint.fat_db, + ); + self.arg_cache_size = Args::select_option( + cli_args.globals.footprint.cache_size, + defaults.footprint.cache_size, + fallback.footprint.cache_size, + ); + self.arg_num_verifiers = Args::select_option( + cli_args.globals.footprint.num_verifiers, + defaults.footprint.num_verifiers, + fallback.footprint.num_verifiers, + ); + self.arg_snapshot_threads = Args::select_option( + cli_args.globals.snapshot.snapshot_threads, + defaults.snapshot.snapshot_threads, + fallback.snapshot.snapshot_threads, + ); + self.arg_secretstore_http_interface = Args::select_value( + cli_args.globals.secret_store.secretstore_http_interface, + defaults.secret_store.secretstore_http_interface, + fallback.secret_store.secretstore_http_interface, + ); + self.arg_max_round_blocks_to_import = Args::select_value( + cli_args.globals.sealing_mining.max_round_blocks_to_import, + defaults.sealing_mining.max_round_blocks_to_import, + fallback.sealing_mining.max_round_blocks_to_import, + ); + self.arg_on_demand_request_backoff_start = Args::select_option( + cli_args + .globals + .light_client + .on_demand_request_backoff_start, + defaults.light_client.on_demand_request_backoff_start, + fallback.light_client.on_demand_request_backoff_start, + ); + self.arg_on_demand_request_backoff_max = Args::select_option( + cli_args.globals.light_client.on_demand_request_backoff_max, + defaults.light_client.on_demand_request_backoff_max, + fallback.light_client.on_demand_request_backoff_max, + ); + self.arg_on_demand_request_backoff_rounds_max = Args::select_option( + cli_args + .globals + .light_client + .on_demand_request_backoff_rounds_max, + defaults.light_client.on_demand_request_backoff_rounds_max, + fallback.light_client.on_demand_request_backoff_rounds_max, + ); + self.arg_on_demand_request_consecutive_failures = Args::select_option( + cli_args + .globals + .light_client + .on_demand_request_consecutive_failures, + defaults.light_client.on_demand_request_consecutive_failures, + fallback.light_client.on_demand_request_consecutive_failures, + ); + self.arg_secretstore_srv_gen_contract = Args::select_option( + cli_args.globals.secret_store.secretstore_srv_gen_contract, + defaults.secret_store.secretstore_srv_gen_contract, + fallback.secret_store.secretstore_srv_gen_contract, + ); + self.arg_secretstore_srv_retr_contract = Args::select_option( + cli_args.globals.secret_store.secretstore_srv_retr_contract, + defaults.secret_store.secretstore_srv_retr_contract, + fallback.secret_store.secretstore_srv_retr_contract, + ); + self.arg_secretstore_doc_store_contract = Args::select_option( + cli_args.globals.secret_store.secretstore_doc_store_contract, + defaults.secret_store.secretstore_doc_store_contract, + fallback.secret_store.secretstore_doc_store_contract, + ); + self.arg_secretstore_doc_sretr_contract = Args::select_option( + cli_args.globals.secret_store.secretstore_doc_sretr_contract, + defaults.secret_store.secretstore_doc_sretr_contract, + fallback.secret_store.secretstore_doc_sretr_contract, + ); + self.arg_secretstore_nodes = Args::select_value( + cli_args.globals.secret_store.secretstore_nodes, + defaults.secret_store.secretstore_nodes, + fallback.secret_store.secretstore_nodes, + ); + self.arg_secretstore_server_set_contract = Args::select_option( + cli_args + .globals + .secret_store + .secretstore_server_set_contract, + defaults.secret_store.secretstore_server_set_contract, + fallback.secret_store.secretstore_server_set_contract, + ); + self.arg_private_signer = Args::select_option( + cli_args.globals.private_transactions.private_signer, + defaults.private_transactions.private_signer, + fallback.private_transactions.private_signer, + ); + } + + fn absorb_global_flags(&mut self, cli_args: &ArgsInput, defaults: &Globals, fallback: &Globals) { + self.arg_enable_signing_queue = cli_args.globals.account.enable_signing_queue + || defaults.account.enable_signing_queue + || fallback.account.enable_signing_queue; + + self.flag_fast_unlock = cli_args.globals.account.fast_unlock + || defaults.account.fast_unlock + || fallback.account.fast_unlock; + + self.flag_no_serve_light = cli_args.globals.networking.no_serve_light + || defaults.networking.no_serve_light + || fallback.networking.no_serve_light; + + self.flag_no_secretstore = cli_args.globals.secret_store.no_secretstore + || defaults.secret_store.no_secretstore + || fallback.secret_store.no_secretstore; + + self.flag_no_secretstore_http = cli_args.globals.secret_store.no_secretstore_http + || defaults.secret_store.no_secretstore_http + || fallback.secret_store.no_secretstore_http; + + self.flag_no_secretstore_auto_migrate = + cli_args.globals.secret_store.no_secretstore_auto_migrate + || defaults.secret_store.no_secretstore_auto_migrate + || fallback.secret_store.no_secretstore_auto_migrate; + + self.flag_no_ws = cli_args.globals.websockets.no_ws + || defaults.websockets.no_ws + || fallback.websockets.no_ws; + + self.flag_no_ipc = + cli_args.globals.ipc.no_ipc || defaults.ipc.no_ipc || fallback.ipc.no_ipc; + + self.flag_force_sealing = cli_args.globals.sealing_mining.force_sealing + || defaults.sealing_mining.force_sealing + || fallback.sealing_mining.force_sealing; + + self.flag_reseal_on_uncle = cli_args.globals.sealing_mining.reseal_on_uncle + || defaults.sealing_mining.reseal_on_uncle + || fallback.sealing_mining.reseal_on_uncle; + + self.flag_remove_solved = cli_args.globals.sealing_mining.remove_solved + || defaults.sealing_mining.remove_solved + || fallback.sealing_mining.remove_solved; + + self.flag_tx_queue_no_unfamiliar_locals = cli_args + .globals + .sealing_mining + .tx_queue_no_unfamiliar_locals + || defaults.sealing_mining.tx_queue_no_unfamiliar_locals + || fallback.sealing_mining.tx_queue_no_unfamiliar_locals; + + self.flag_tx_queue_no_early_reject = + cli_args.globals.sealing_mining.tx_queue_no_early_reject + || defaults.sealing_mining.tx_queue_no_early_reject + || fallback.sealing_mining.tx_queue_no_early_reject; + + self.flag_refuse_service_transactions = + cli_args.globals.sealing_mining.refuse_service_transactions + || defaults.sealing_mining.refuse_service_transactions + || fallback.sealing_mining.refuse_service_transactions; + + self.flag_infinite_pending_block = cli_args.globals.sealing_mining.infinite_pending_block + || defaults.sealing_mining.infinite_pending_block + || fallback.sealing_mining.infinite_pending_block; + + self.flag_no_persistent_txqueue = cli_args.globals.sealing_mining.no_persistent_txqueue + || defaults.sealing_mining.no_persistent_txqueue + || fallback.sealing_mining.no_persistent_txqueue; + + self.flag_stratum = cli_args.globals.sealing_mining.stratum + || defaults.sealing_mining.stratum + || fallback.sealing_mining.stratum; + + self.flag_no_seal_check = cli_args.globals.import_export.no_seal_check + || defaults.import_export.no_seal_check + || fallback.import_export.no_seal_check; + + self.flag_can_restart = cli_args.globals.internal.can_restart + || defaults.internal.can_restart + || fallback.internal.can_restart; + + self.flag_no_color = cli_args.globals.miscellaneous.no_color + || defaults.miscellaneous.no_color + || fallback.miscellaneous.no_color; + + self.flag_no_config = cli_args.globals.miscellaneous.no_config + || defaults.miscellaneous.no_config + || fallback.miscellaneous.no_config; + + self.flag_scale_verifiers = cli_args.globals.footprint.scale_verifiers + || defaults.footprint.scale_verifiers + || fallback.footprint.scale_verifiers; + + self.flag_no_periodic_snapshot = cli_args.globals.snapshot.no_periodic_snapshot + || defaults.snapshot.no_periodic_snapshot + || fallback.snapshot.no_periodic_snapshot; + + self.flag_no_download = cli_args.globals.operating.no_download + || defaults.operating.no_download + || fallback.operating.no_download; + + self.flag_no_consensus = cli_args.globals.operating.no_consensus + || defaults.operating.no_consensus + || fallback.operating.no_consensus; + + self.flag_light = cli_args.globals.operating.light + || defaults.operating.light + || fallback.operating.light; + + self.flag_no_hardcoded_sync = cli_args.globals.operating.light + || defaults.operating.light + || fallback.operating.light; + + self.flag_force_direct = cli_args.globals.operating.force_direct + || defaults.operating.force_direct + || fallback.operating.force_direct; + + self.flag_unsafe_expose = cli_args.globals.convenience.unsafe_expose + || defaults.convenience.unsafe_expose + || fallback.convenience.unsafe_expose; + + self.flag_private_enabled = cli_args.globals.private_transactions.private_enabled + || defaults.private_transactions.private_enabled + || fallback.private_transactions.private_enabled; + + self.flag_private_state_offchain = + cli_args.globals.private_transactions.private_state_offchain + || defaults.private_transactions.private_state_offchain + || fallback.private_transactions.private_state_offchain; + + self.flag_jsonrpc_allow_missing_blocks = + cli_args.globals.http_json_rpc.jsonrpc_allow_missing_blocks + || defaults.http_json_rpc.jsonrpc_allow_missing_blocks + || fallback.http_json_rpc.jsonrpc_allow_missing_blocks; + + self.flag_no_jsonrpc = cli_args.globals.http_json_rpc.no_jsonrpc + || defaults.http_json_rpc.no_jsonrpc + || fallback.http_json_rpc.no_jsonrpc; + + self.flag_jsonrpc_no_keep_alive = cli_args.globals.http_json_rpc.jsonrpc_no_keep_alive + || defaults.http_json_rpc.jsonrpc_no_keep_alive + || fallback.http_json_rpc.jsonrpc_no_keep_alive; + + self.flag_jsonrpc_experimental = cli_args.globals.http_json_rpc.jsonrpc_experimental + || defaults.http_json_rpc.jsonrpc_experimental + || fallback.http_json_rpc.jsonrpc_experimental; + + self.flag_no_warp = cli_args.globals.networking.no_warp + || defaults.networking.no_warp + || fallback.networking.no_warp; + + self.flag_no_discovery = cli_args.globals.networking.no_discovery + || defaults.networking.no_discovery + || fallback.networking.no_discovery; + + self.flag_reserved_only = cli_args.globals.networking.reserved_only + || defaults.networking.reserved_only + || fallback.networking.reserved_only; + + self.flag_no_ancient_blocks = cli_args.globals.networking.no_ancient_blocks + || defaults.networking.no_ancient_blocks + || fallback.networking.no_ancient_blocks; + + self.flag_geth = + cli_args.globals.legacy.geth || defaults.legacy.geth || fallback.legacy.geth; + + self.flag_import_geth_keys = cli_args.globals.legacy.import_geth_keys + || defaults.legacy.import_geth_keys + || fallback.legacy.import_geth_keys; + } +} diff --git a/parity/cli/config.rs b/parity/cli/config.rs new file mode 100644 index 00000000000..ac6b0723921 --- /dev/null +++ b/parity/cli/config.rs @@ -0,0 +1,17 @@ +use cli::args::ArgsError; +use rust_embed::RustEmbed; + +#[derive(RustEmbed)] +#[folder = "parity/cli/config"] +struct Config; + +pub fn get_config(config_name: &str) -> Result { + Config::get(config_name) + .ok_or_else(|| "does not exist".to_owned()) + // .and_then(|x| srt(x).map_err(|e| e.to_owned())) + .and_then(|x| String::from_utf8(x.to_vec()).map_err(|e| e.to_string())) + .map_err(|e| ArgsError::ConfigReadError(format!( + "Failure to read config file {}: {}", + config_name, e + ))) +} diff --git a/parity/cli/config/config_default.toml b/parity/cli/config/config_default.toml new file mode 100644 index 00000000000..2f4025b3f58 --- /dev/null +++ b/parity/cli/config/config_default.toml @@ -0,0 +1,151 @@ +[operating] +no_download = false +no_consensus = false +light = false +no_hardcoded_sync = false +force_direct = false +mode = "last" +mode_timeout = 300 +mode_alarm = 3600 +auto_update = "critical" +auto_update_delay = 100 +auto_update_check_frequency = 20 +release_track = "current" +chain = "foundation" +keys_path = "$BASE/keys" +identity = "" + +[convenience] +unsafe_expose = false +config = "$BASE/config.toml" +ports_shift = 0 + +[account] +enable_signing_queue = false +fast_unlock = false +keys_iterations = 10240 +accounts_refresh = 5 +password = [] + +[private_transactions] +private_enabled = false +private_state_offchain = false + +[ui_options] +ui_path = "$BASE/signer" + +[networking] +no_warp = false +no_discovery = false +reserved_only = false +no_ancient_blocks = false +no_serve_light = false +port = 30303 +interface = "all" +snapshot_peers = 0 +nat = "any" +allow_ips = "all" +max_pending_peers = 64 + +[ipc] +ipc_chmod = "660" +no_ipc = false +ipc_apis = "web3,eth,pubsub,net,parity,parity_pubsub,parity_accounts,private,traces,rpc,parity_transactions_pool" + +[http_json_rpc] +jsonrpc_allow_missing_blocks = false +no_jsonrpc = false +jsonrpc_no_keep_alive = false +jsonrpc_experimental = false +jsonrpc_port = 8545 +jsonrpc_interface = "local" +jsonrpc_apis = "web3,eth,pubsub,net,parity,private,parity_pubsub,traces,rpc,parity_transactions_pool" +jsonrpc_hosts = "none" +jsonrpc_server_threads = 4 +jsonrpc_cors = "none" +poll_lifetime = 60 + +[light_client] + +[websockets] +no_ws = false +ws_port = 8546 +ws_interface = "local" +ws_apis = "web3,eth,pubsub,net,parity,parity_pubsub,private,traces,rpc,parity_transactions_pool" +ws_origins = "parity://*,chrome-extension://*,moz-extension://*" +ws_hosts = "none" +ws_max_connections = 100 + +[secret_store] +no_secretstore = false +no_secretstore_http = false +no_secretstore_auto_migrate = false +secretstore_http_cors = "none" +secretstore_acl_contract = "registry" +secretstore_nodes = "" +secretstore_server_set_contract = "registry" +secretstore_interface = "local" +secretstore_port = 8083 +secretstore_http_interface = "local" +secretstore_http_port = 8082 +secretstore_path = "$BASE/secretstore" + +[sealing_mining] +force_sealing = false +reseal_on_uncle = false +remove_solved = false +reseal_on_txs = "own" +reseal_min_period = 2000 +reseal_max_period = 120000 +work_queue_size = 20 +relay_set = "cheap" +usd_per_tx = "0.0001" +usd_per_eth = "auto" +price_update_period = "hourly" +gas_floor_target = "8000000" +gas_cap = "10000000" +tx_queue_mem_limit = 4 +tx_queue_size = 8192 +tx_queue_strategy = "gas_price" +stratum_interface = "local" +stratum_port = 8008 +gas_price_percentile = 50 +max_round_blocks_to_import = 12 +tx_queue_no_unfamiliar_locals = false +tx_queue_no_early_reject = false +refuse_service_transactions = false +infinite_pending_block = false +no_persistent_txqueue = false +stratum = false + +[internal] +can_restart = false + +[miscellaneous] +no_color = false +no_config = false + + +[footprint] +scale_verifiers = false +tracing = "auto" +pruning = "auto" +pruning_history = 128 +pruning_memory = 64 +cache_size_db = 128 +cache_size_blocks = 8 +cache_size_queue = 40 +cache_size_state = 25 +db_compaction = "auto" +fat_db = "auto" + +[import_export] +no_seal_check = false + +[snapshot] +no_periodic_snapshot = false + +[legacy] +geth = false +import_geth_keys = false + diff --git a/parity/cli/config/config_dev.toml b/parity/cli/config/config_dev.toml new file mode 100644 index 00000000000..7461c0348a6 --- /dev/null +++ b/parity/cli/config/config_dev.toml @@ -0,0 +1,158 @@ +[operating] +no_download = false +no_consensus = false +light = false +no_hardcoded_sync = false +force_direct = false +mode = "last" +mode_timeout = 300 +mode_alarm = 3600 +auto_update = "critical" +auto_update_delay = 100 +auto_update_check_frequency = 20 +release_track = "current" +keys_path = "$BASE/keys" +identity = "" + +# Preset specific changes + +chain = "dev" + +[convenience] +unsafe_expose = false +config = "$BASE/config.toml" +ports_shift = 0 + +[account] +enable_signing_queue = false +fast_unlock = false +keys_iterations = 10240 +accounts_refresh = 5 +password = [] + +[private_transactions] +private_enabled = false +private_state_offchain = false + +[ui_options] +ui_path = "$BASE/signer" + +[networking] +no_warp = false +no_discovery = false +reserved_only = false +no_ancient_blocks = false +no_serve_light = false +port = 30303 +interface = "all" +snapshot_peers = 0 +nat = "any" +allow_ips = "all" +max_pending_peers = 64 + +[ipc] +ipc_chmod = "660" +no_ipc = false +ipc_apis = "web3,eth,pubsub,net,parity,parity_pubsub,parity_accounts,private,traces,rpc,parity_transactions_pool" + +[http_json_rpc] +jsonrpc_allow_missing_blocks = false +no_jsonrpc = false +jsonrpc_no_keep_alive = false +jsonrpc_experimental = false +jsonrpc_port = 8545 +jsonrpc_interface = "local" +jsonrpc_apis = "web3,eth,pubsub,net,parity,private,parity_pubsub,traces,rpc,parity_transactions_pool" +jsonrpc_hosts = "none" +jsonrpc_server_threads = 4 +jsonrpc_cors = "none" +poll_lifetime = 60 + +[light_client] + +[websockets] +no_ws = false +ws_port = 8546 +ws_interface = "local" +ws_apis = "web3,eth,pubsub,net,parity,parity_pubsub,private,traces,rpc,parity_transactions_pool" +ws_origins = "parity://*,chrome-extension://*,moz-extension://*" +ws_hosts = "none" +ws_max_connections = 100 + +[secret_store] +no_secretstore = false +no_secretstore_http = false +no_secretstore_auto_migrate = false +secretstore_http_cors = "none" +secretstore_acl_contract = "registry" +secretstore_nodes = "" +secretstore_server_set_contract = "registry" +secretstore_interface = "local" +secretstore_port = 8083 +secretstore_http_interface = "local" +secretstore_http_port = 8082 +secretstore_path = "$BASE/secretstore" + +[sealing_mining] +force_sealing = false +reseal_on_uncle = false +remove_solved = false +reseal_on_txs = "own" +reseal_max_period = 120000 +work_queue_size = 20 +relay_set = "cheap" +usd_per_tx = "0.0001" +usd_per_eth = "auto" +price_update_period = "hourly" +gas_floor_target = "8000000" +gas_cap = "10000000" +tx_queue_mem_limit = 4 +tx_queue_size = 8192 +tx_queue_strategy = "gas_price" +stratum_interface = "local" +stratum_port = 8008 +gas_price_percentile = 50 +max_round_blocks_to_import = 12 +tx_queue_no_unfamiliar_locals = false +tx_queue_no_early_reject = false +refuse_service_transactions = false +infinite_pending_block = false +no_persistent_txqueue = false +stratum = false + +# Preset specific changes + +reseal_min_period = 0 +min_gas_price = 0 + +[internal] +can_restart = false + +[miscellaneous] +no_color = false +no_config = false + + +[footprint] +scale_verifiers = false +tracing = "auto" +pruning = "auto" +pruning_history = 128 +pruning_memory = 64 +cache_size_db = 128 +cache_size_blocks = 8 +cache_size_queue = 40 +cache_size_state = 25 +db_compaction = "auto" +fat_db = "auto" + +[import_export] +no_seal_check = false + +[snapshot] +no_periodic_snapshot = false + +[legacy] +geth = false +import_geth_keys = false + diff --git a/parity/cli/config/config_dev_insecure.toml b/parity/cli/config/config_dev_insecure.toml new file mode 100644 index 00000000000..37482d2ca11 --- /dev/null +++ b/parity/cli/config/config_dev_insecure.toml @@ -0,0 +1,158 @@ +[operating] +chain = "dev" +no_download = false +light = false +no_hardcoded_sync = false +force_direct = false +mode = "last" +mode_timeout = 300 +mode_alarm = 3600 +auto_update = "critical" +auto_update_delay = 100 +auto_update_check_frequency = 20 +release_track = "current" +keys_path = "$BASE/keys" +identity = "" +no_consensus = true + +[convenience] +unsafe_expose = false +config = "$BASE/config.toml" +ports_shift = 0 + +[account] +enable_signing_queue = false +fast_unlock = false +keys_iterations = 10240 +accounts_refresh = 5 +password = [] + +[private_transactions] +private_enabled = false +private_state_offchain = false + +[ui_options] +ui_path = "$BASE/signer" + +[networking] +no_warp = false +no_discovery = false +reserved_only = false +no_ancient_blocks = false +no_serve_light = false +port = 30303 +interface = "all" +snapshot_peers = 0 +nat = "any" +allow_ips = "all" +max_pending_peers = 64 + +[ipc] +ipc_chmod = "660" +no_ipc = false +ipc_apis = "web3,eth,pubsub,net,parity,parity_pubsub,parity_accounts,private,traces,rpc,parity_transactions_pool" + +[http_json_rpc] +jsonrpc_allow_missing_blocks = false +no_jsonrpc = false +jsonrpc_no_keep_alive = false +jsonrpc_experimental = false +jsonrpc_port = 8545 +jsonrpc_server_threads = 4 +jsonrpc_cors = "none" +poll_lifetime = 60 + +# Preset specific changes + +jsonrpc_interface = "all" +jsonrpc_apis = "all" +jsonrpc_hosts = "all" + +[light_client] + +[websockets] +no_ws = false +ws_port = 8546 +ws_interface = "local" +ws_apis = "web3,eth,pubsub,net,parity,parity_pubsub,private,traces,rpc,parity_transactions_pool" +ws_origins = "parity://*,chrome-extension://*,moz-extension://*" +ws_hosts = "none" +ws_max_connections = 100 + +[secret_store] +no_secretstore = false +no_secretstore_http = false +no_secretstore_auto_migrate = false +secretstore_http_cors = "none" +secretstore_acl_contract = "registry" +secretstore_nodes = "" +secretstore_server_set_contract = "registry" +secretstore_interface = "local" +secretstore_port = 8083 +secretstore_http_interface = "local" +secretstore_http_port = 8082 +secretstore_path = "$BASE/secretstore" + +[sealing_mining] +force_sealing = false +reseal_on_uncle = false +remove_solved = false +reseal_on_txs = "own" +reseal_max_period = 120000 +work_queue_size = 20 +relay_set = "cheap" +usd_per_tx = "0.0001" +usd_per_eth = "auto" +price_update_period = "hourly" +gas_floor_target = "8000000" +gas_cap = "10000000" +tx_queue_mem_limit = 4 +tx_queue_size = 8192 +tx_queue_strategy = "gas_price" +stratum_interface = "local" +stratum_port = 8008 +gas_price_percentile = 50 +max_round_blocks_to_import = 12 +tx_queue_no_unfamiliar_locals = false +tx_queue_no_early_reject = false +refuse_service_transactions = false +infinite_pending_block = false +no_persistent_txqueue = false +stratum = false + +# Preset specific changes + +reseal_min_period = 0 +min_gas_pric = 0 + +[internal] +can_restart = false + +[miscellaneous] +no_color = false +no_config = false + + +[footprint] +scale_verifiers = false +tracing = "auto" +pruning = "auto" +pruning_history = 128 +pruning_memory = 64 +cache_size_db = 128 +cache_size_blocks = 8 +cache_size_queue = 40 +cache_size_state = 25 +db_compaction = "auto" +fat_db = "auto" + +[import_export] +no_seal_check = false + +[snapshot] +no_periodic_snapshot = false + +[legacy] +geth = false +import_geth_keys = false + diff --git a/parity/cli/config/config_insecure.toml b/parity/cli/config/config_insecure.toml new file mode 100644 index 00000000000..d7a003cc0a6 --- /dev/null +++ b/parity/cli/config/config_insecure.toml @@ -0,0 +1,157 @@ +[operating] +no_download = false +light = false +no_hardcoded_sync = false +force_direct = false +mode = "last" +mode_timeout = 300 +mode_alarm = 3600 +auto_update = "critical" +auto_update_delay = 100 +auto_update_check_frequency = 20 +release_track = "current" +chain = "foundation" +keys_path = "$BASE/keys" +identity = "" + +# Preset specific changes + +no_consensus = true + +[convenience] +unsafe_expose = false +config = "$BASE/config.toml" +ports_shift = 0 + +[account] +enable_signing_queue = false +fast_unlock = false +keys_iterations = 10240 +accounts_refresh = 5 +password = [] + +[private_transactions] +private_enabled = false +private_state_offchain = false + +[ui_options] +ui_path = "$BASE/signer" + +[networking] +no_warp = false +no_discovery = false +reserved_only = false +no_ancient_blocks = false +no_serve_light = false +port = 30303 +interface = "all" +snapshot_peers = 0 +nat = "any" +allow_ips = "all" +max_pending_peers = 64 + +[ipc] +ipc_chmod = "660" +no_ipc = false +ipc_apis = "web3,eth,pubsub,net,parity,parity_pubsub,parity_accounts,private,traces,rpc,parity_transactions_pool" + +[http_json_rpc] +jsonrpc_allow_missing_blocks = false +no_jsonrpc = false +jsonrpc_no_keep_alive = false +jsonrpc_experimental = false +jsonrpc_port = 8545 +jsonrpc_server_threads = 4 +jsonrpc_cors = "none" +poll_lifetime = 60 + +# Preset specific changes + +jsonrpc_interface = "all" +jsonrpc_apis = "all" +jsonrpc_hosts = "all" + +[light_client] + +[websockets] +no_ws = false +ws_port = 8546 +ws_interface = "local" +ws_apis = "web3,eth,pubsub,net,parity,parity_pubsub,private,traces,rpc,parity_transactions_pool" +ws_origins = "parity://*,chrome-extension://*,moz-extension://*" +ws_hosts = "none" +ws_max_connections = 100 + +[secret_store] +no_secretstore = false +no_secretstore_http = false +no_secretstore_auto_migrate = false +secretstore_http_cors = "none" +secretstore_acl_contract = "registry" +secretstore_nodes = "" +secretstore_server_set_contract = "registry" +secretstore_interface = "local" +secretstore_port = 8083 +secretstore_http_interface = "local" +secretstore_http_port = 8082 +secretstore_path = "$BASE/secretstore" + +[sealing_mining] +force_sealing = false +reseal_on_uncle = false +remove_solved = false +reseal_on_txs = "own" +reseal_min_period = 2000 +reseal_max_period = 120000 +work_queue_size = 20 +relay_set = "cheap" +usd_per_tx = "0.0001" +usd_per_eth = "auto" +price_update_period = "hourly" +gas_floor_target = "8000000" +gas_cap = "10000000" +tx_queue_mem_limit = 4 +tx_queue_size = 8192 +tx_queue_strategy = "gas_price" +stratum_interface = "local" +stratum_port = 8008 +gas_price_percentile = 50 +max_round_blocks_to_import = 12 +tx_queue_no_unfamiliar_locals = false +tx_queue_no_early_reject = false +refuse_service_transactions = false +infinite_pending_block = false +no_persistent_txqueue = false +stratum = false + +[internal] +can_restart = false + +[miscellaneous] +no_color = false +no_config = false + + +[footprint] +scale_verifiers = false +tracing = "auto" +pruning = "auto" +pruning_history = 128 +pruning_memory = 64 +cache_size_db = 128 +cache_size_blocks = 8 +cache_size_queue = 40 +cache_size_state = 25 +db_compaction = "auto" +fat_db = "auto" + +[import_export] +no_seal_check = false + +[snapshot] +no_periodic_snapshot = false + +[legacy] +geth = false +import_geth_keys = false + diff --git a/parity/cli/config/config_mining.toml b/parity/cli/config/config_mining.toml new file mode 100644 index 00000000000..c87040a1d30 --- /dev/null +++ b/parity/cli/config/config_mining.toml @@ -0,0 +1,182 @@ +[operating] +no_download = false +no_consensus = false +light = false +no_hardcoded_sync = false +force_direct = false +mode = "last" +mode_timeout = 300 +mode_alarm = 3600 +auto_update = "critical" +auto_update_delay = 100 +auto_update_check_frequency = 20 +release_track = "current" +chain = "foundation" +keys_path = "$BASE/keys" +identity = "" + +[convenience] +unsafe_expose = false +config = "$BASE/config.toml" +ports_shift = 0 + +[account] +enable_signing_queue = false +fast_unlock = false +keys_iterations = 10240 +accounts_refresh = 5 +password = [] + +[private_transactions] +private_enabled = false +private_state_offchain = false + +[ui_options] +ui_path = "$BASE/signer" + +[networking] +no_warp = false +no_discovery = false +reserved_only = false +no_ancient_blocks = false +no_serve_light = false +port = 30303 +interface = "all" +snapshot_peers = 0 +nat = "any" +allow_ips = "all" +max_pending_peers = 64 + +# preset specific options + +# openethereum will try to maintain connection to at least 50 peers +min_peers = 50 +max_peers = 100 + +[ipc] +ipc_chmod = "660" +no_ipc = true +ipc_apis = "web3,eth,pubsub,net,parity,parity_pubsub,parity_accounts,private,traces,rpc,parity_transactions_pool" + +# preset specific options + +# You won't be able to use IPC to interact with openethereum +disable = true + +[http_json_rpc] +jsonrpc_allow_missing_blocks = false +no_jsonrpc = false +jsonrpc_no_keep_alive = false +jsonrpc_experimental = false +jsonrpc_port = 8545 +jsonrpc_interface = "local" +jsonrpc_apis = "web3,eth,pubsub,net,parity,private,parity_pubsub,traces,rpc,parity_transactions_pool" +jsonrpc_hosts = "none" +jsonrpc_server_threads = 4 +jsonrpc_cors = "none" +poll_lifetime = 60 + +[light_client] + +[websockets] +no_ws = false +ws_port = 8546 +ws_interface = "local" +ws_apis = "web3,eth,pubsub,net,parity,parity_pubsub,private,traces,rpc,parity_transactions_pool" +ws_origins = "parity://*,chrome-extension://*,moz-extension://*" +ws_hosts = "none" +ws_max_connections = 100 + +[secret_store] +no_secretstore = false +no_secretstore_http = false +no_secretstore_auto_migrate = false +secretstore_http_cors = "none" +secretstore_acl_contract = "registry" +secretstore_nodes = "" +secretstore_server_set_contract = "registry" +secretstore_interface = "local" +secretstore_port = 8083 +secretstore_http_interface = "local" +secretstore_http_port = 8082 +secretstore_path = "$BASE/secretstore" + +[sealing_mining] +reseal_on_uncle = false +remove_solved = false +reseal_max_period = 120000 +work_queue_size = 20 +relay_set = "cheap" +usd_per_tx = "0.0001" +usd_per_eth = "auto" +price_update_period = "hourly" +gas_floor_target = "8000000" +gas_cap = "10000000" +tx_queue_mem_limit = 4 +tx_queue_strategy = "gas_price" +stratum_interface = "local" +stratum_port = 8008 +gas_price_percentile = 50 +max_round_blocks_to_import = 12 +tx_queue_no_unfamiliar_locals = false +tx_queue_no_early_reject = false +refuse_service_transactions = false +infinite_pending_block = false +no_persistent_txqueue = false +stratum = false + +# Preset specific options + +# Prepare a block to seal when there are no miners connected +force_sealing = true +# New pending block will be created for all transactions (both local and external) +reseal_on_txs = "all" +# New pending block will only be created once every 4000 seconds +reseal_min_period = 4000 +# Openethereum will keep/relay at most 8192 transactions per queue +tx_queue_size = 8192 +tx_queue_per_sender = 128 + + + +[internal] +can_restart = false + +[miscellaneous] +no_color = false +no_config = false + +# Preset specific options + +# Logging pattern (`=`, e.g. `own_tx=trace`). +logging = "miner=trace,own_tx=trace" + + +[footprint] +scale_verifiers = false +tracing = "auto" +pruning = "auto" +pruning_history = 128 +pruning_memory = 64 +cache_size_db = 128 +cache_size_blocks = 8 +cache_size_queue = 40 +cache_size_state = 25 +db_compaction = "auto" +fat_db = "auto" + +# preset specific options + +# If defined will never use more than 1024 for all caches (Overrides other cache settings) +cache_size = 1024 + +[import_export] +no_seal_check = false + +[snapshot] +no_periodic_snapshot = false + +[legacy] +geth = false +import_geth_keys = false + diff --git a/parity/cli/config/config_non_standard_ports.toml b/parity/cli/config/config_non_standard_ports.toml new file mode 100644 index 00000000000..7fa075842bb --- /dev/null +++ b/parity/cli/config/config_non_standard_ports.toml @@ -0,0 +1,160 @@ +[operating] +no_download = false +no_consensus = false +light = false +no_hardcoded_sync = false +force_direct = false +mode = "last" +mode_timeout = 300 +mode_alarm = 3600 +auto_update = "critical" +auto_update_delay = 100 +auto_update_check_frequency = 20 +release_track = "current" +chain = "foundation" +keys_path = "$BASE/keys" +identity = "" + +[convenience] +unsafe_expose = false +config = "$BASE/config.toml" +ports_shift = 0 + +[account] +enable_signing_queue = false +fast_unlock = false +keys_iterations = 10240 +accounts_refresh = 5 +password = [] + +[private_transactions] +private_enabled = false +private_state_offchain = false + +[ui_options] +ui_path = "$BASE/signer" + +[networking] +no_warp = false +no_discovery = false +reserved_only = false +no_ancient_blocks = false +no_serve_light = false +interface = "all" +snapshot_peers = 0 +nat = "any" +allow_ips = "all" +max_pending_peers = 64 + +# Preset specific change + +# Openethereum will listen for connections on port 30305 +port = 30305 + +[ipc] +ipc_chmod = "660" +no_ipc = false +ipc_apis = "web3,eth,pubsub,net,parity,parity_pubsub,parity_accounts,private,traces,rpc,parity_transactions_pool" + +[http_json_rpc] +jsonrpc_allow_missing_blocks = false +no_jsonrpc = false +jsonrpc_no_keep_alive = false +jsonrpc_experimental = false +jsonrpc_port = 8645 +jsonrpc_interface = "local" +jsonrpc_apis = "web3,eth,pubsub,net,parity,private,parity_pubsub,traces,rpc,parity_transactions_pool" +jsonrpc_hosts = "none" +jsonrpc_server_threads = 4 +jsonrpc_cors = "none" +poll_lifetime = 60 + +# Preset specific change + +# JSON-RPC over HTTP will be available on port 8645 +port = 8645 + +[light_client] + +[websockets] +no_ws = false +ws_port = 8546 +ws_interface = "local" +ws_apis = "web3,eth,pubsub,net,parity,parity_pubsub,private,traces,rpc,parity_transactions_pool" +ws_origins = "parity://*,chrome-extension://*,moz-extension://*" +ws_hosts = "none" +ws_max_connections = 100 + +[secret_store] +no_secretstore = false +no_secretstore_http = false +no_secretstore_auto_migrate = false +secretstore_http_cors = "none" +secretstore_acl_contract = "registry" +secretstore_nodes = "" +secretstore_server_set_contract = "registry" +secretstore_interface = "local" +secretstore_port = 8083 +secretstore_http_interface = "local" +secretstore_http_port = 8082 +secretstore_path = "$BASE/secretstore" + +[sealing_mining] +force_sealing = false +reseal_on_uncle = false +remove_solved = false +reseal_on_txs = "own" +reseal_min_period = 2000 +reseal_max_period = 120000 +work_queue_size = 20 +relay_set = "cheap" +usd_per_tx = "0.0001" +usd_per_eth = "auto" +price_update_period = "hourly" +gas_floor_target = "8000000" +gas_cap = "10000000" +tx_queue_mem_limit = 4 +tx_queue_size = 8192 +tx_queue_strategy = "gas_price" +stratum_interface = "local" +stratum_port = 8008 +gas_price_percentile = 50 +max_round_blocks_to_import = 12 +tx_queue_no_unfamiliar_locals = false +tx_queue_no_early_reject = false +refuse_service_transactions = false +infinite_pending_block = false +no_persistent_txqueue = false +stratum = false + +[internal] +can_restart = false + +[miscellaneous] +no_color = false +no_config = false + + +[footprint] +scale_verifiers = false +tracing = "auto" +pruning = "auto" +pruning_history = 128 +pruning_memory = 64 +cache_size_db = 128 +cache_size_blocks = 8 +cache_size_queue = 40 +cache_size_state = 25 +db_compaction = "auto" +fat_db = "auto" + +[import_export] +no_seal_check = false + +[snapshot] +no_periodic_snapshot = false + +[legacy] +geth = false +import_geth_keys = false + diff --git a/parity/cli/config/test_config.toml b/parity/cli/config/test_config.toml new file mode 100644 index 00000000000..f80dbf3a304 --- /dev/null +++ b/parity/cli/config/test_config.toml @@ -0,0 +1,80 @@ +[operating] +no_download = false +no_consensus = false +light = false +no_hardcoded_sync = false +force_direct = false + +[convenience] +unsafe_expose = false + +[account] +fast_unlock = false +enable_signing_queue = false +password = [] + +[private_transactions] +private_enabled = false +private_state_offchain = false + +[ui_options] + +[networking] +no_warp = false +no_discovery = false +reserved_only = false +no_ancient_blocks = false +no_serve_light = false + +[ipc] +no_ipc = false + +[http_json_rpc] +jsonrpc_allow_missing_blocks = false +no_jsonrpc = false +jsonrpc_no_keep_alive = false +jsonrpc_experimental = false + +[light_client] + +[websockets] +no_ws = false + +[secret_store] +no_secretstore = false +no_secretstore_http = false +no_secretstore_auto_migrate = false + +[sealing_mining] +force_sealing = false +reseal_on_uncle = false +remove_solved = false +tx_queue_no_unfamiliar_locals = false +tx_queue_no_early_reject = false +refuse_service_transactions = false +infinite_pending_block = false +no_persistent_txqueue = false +stratum = true +stratum_interface = "some interface" +stratum_port = 8007 +stratum_secret = "Yellow" + +[internal] +can_restart = false + +[miscellaneous] +no_color = false +no_config = false + +[footprint] +scale_verifiers = false + +[import_export] +no_seal_check = false + +[snapshot] +no_periodic_snapshot = false + +[legacy] +geth = false +import_geth_keys = false diff --git a/parity/cli/globals.rs b/parity/cli/globals.rs new file mode 100644 index 00000000000..39c7d4440f0 --- /dev/null +++ b/parity/cli/globals.rs @@ -0,0 +1,1177 @@ +use serde_derive::{Deserialize, Serialize}; +use structopt::StructOpt; + +#[derive(PartialEq, Default, StructOpt, Serialize, Deserialize, Debug, Clone)] +pub struct Globals { + #[structopt(flatten)] + pub operating: OperatingOptions, + + #[structopt(flatten)] + pub convenience: ConvenienceOptions, + + #[structopt(flatten)] + pub account: AccountOptions, + + #[structopt(flatten)] + pub private_transactions: PrivateTransactions, + + #[structopt(flatten)] + pub ui_options: UIOptons, + + #[structopt(flatten)] + pub networking: NetworkingOptions, + + #[structopt(flatten)] + pub ipc: IPCOptions, + + #[structopt(flatten)] + pub http_json_rpc: HttpJsonRpcOptions, + + #[structopt(flatten)] + pub light_client: LightClientOptions, + + #[structopt(flatten)] + pub websockets: WebsocketsOptions, + + #[structopt(flatten)] + pub secret_store: SecretStoreOptions, + + #[structopt(flatten)] + pub sealing_mining: SealingMiningOptions, + + #[structopt(flatten)] + pub internal: InternalOptions, + + #[structopt(flatten)] + pub miscellaneous: MiscellaneousOptions, + + #[structopt(flatten)] + pub footprint: FootPrintOptions, + + #[structopt(flatten)] + pub import_export: ImportExportOptions, + + #[structopt(flatten)] + pub snapshot: SnapshotOptions, + + #[structopt(flatten)] + pub legacy: LegacyOptions, +} + +#[derive(StructOpt, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] +pub struct OperatingOptions { + #[structopt( + long = "no-download", + help = "Normally new releases will be downloaded ready for updating. This disables it. Not recommended." + )] + pub no_download: bool, + + #[structopt( + long = "no-consensus", + help = "Force the binary to run even if there are known issues regarding consensus. Not recommended." + )] + pub no_consensus: bool, + + #[structopt( + long, + help = "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." + )] + pub light: bool, + + #[structopt( + long = "no-hardcoded-sync", + help = "By default, if there is no existing database the light client will automatically jump to a block hardcoded in the chain's specifications. This disables this feature." + )] + pub no_hardcoded_sync: bool, + + #[structopt( + long = "force-direct", + help = "Run the originally installed version of Parity, ignoring any updates that have since been installed." + )] + pub force_direct: bool, + + #[structopt( + name = "MODE", + long, + help = "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 JSON-RPC is active; offline - Parity doesn't sync." + )] + pub mode: Option, + + #[structopt( + long = "mode-timeout", + name = "TIMEOUT_IN_SECS", + help = "Specify the number of seconds before inactivity timeout occurs when mode is dark or passive" + )] + pub mode_timeout: Option, + + #[structopt( + long = "mode-alarm", + name = "ALARM_IN_SECS", + help = "Specify the number of seconds before auto sleep reawake timeout occurs when mode is passive" + )] + pub mode_alarm: Option, + + #[structopt( + long = "auto-update", + name = "SET", + help = "Set a releases set to automatically update and install. SET can be one of: all - All updates in the our release track; critical - Only consensus/security updates; none - No updates will be auto-installed." + )] + pub auto_update: Option, + + #[structopt( + long = "auto-update-delay", + name = "DELAY_NUM", + help = "Specify the maximum number of blocks used for randomly delaying updates." + )] + pub auto_update_delay: Option, + + #[structopt( + long = "auto-update-check-frequency", + name = "FREQUENCY_NUM", + help = "Specify the number of blocks between each auto-update check." + )] + pub auto_update_check_frequency: Option, + + #[structopt( + long = "release-track", + name = "TRACK", + help = "Set which release track we should use for updates. TRACK can be one of: stable - Stable releases; nightly - Nightly releases (unstable); testing - Testing releases (do not use); current - Whatever track this executable was released on." + )] + pub release_track: Option, + + #[structopt( + long, + name = "CHAIN", + help = "Specify the blockchain type. CHAIN may be either a JSON chain specification file or ethereum, classic, classic-no-phoenix, poacore, xdai, volta, ewc, musicoin, ellaism, mix, callisto, ethercore, mordor, ropsten, kovan, rinkeby, goerli, kotti, poasokol, testnet, evantestcore, evancore or dev." + )] + pub chain: Option, + + #[structopt( + long = "keys-path", + name = "KEYS_PATH", + help = "Specify the path for JSON key files to be found" + )] + pub keys_path: Option, + + #[structopt(name = "NAME", long, help = "Specify your node's name.")] + pub identity: Option, + + #[structopt( + short = "d", + long = "base-path", + name = "BASE_PATH", + help = "Specify the base data storage path." + )] + pub base_path: Option, + + #[structopt( + name = "DB_PATH", + long = "db-path", + help = "Specify the database directory path" + )] + pub db_path: Option, + + #[clap( + long = "sync-until", + name = "BLOCK_TO_SYNC_UNTIL", + about = "Sync until the given block has been imported, then enter offline mode. Intended for debug/benchmarking only.", + help_heading = Some(OPERATING), + )] + pub sync_until: Option, +} + +#[derive(StructOpt, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] +pub struct ConvenienceOptions { + #[structopt( + long = "unsafe-expose", + help = "All servers will listen on external interfaces and will be remotely accessible. It's equivalent with setting the following: --[ws,jsonrpc,secretstore,stratum,dapps,secretstore-http]-interface=all --*-hosts=all This option is UNSAFE and should be used with great care!" + )] + pub unsafe_expose: bool, + + #[structopt( + short, + long, + name = "CONFIG", + help = "Specify a configuration. CONFIG may be either a configuration file or a preset: dev, insecure, dev-insecure, mining, or non-standard-ports." + )] + pub config: Option, + + #[structopt( + long = "config-generate", + name = "PATH_TO_GENERATE_CONFIG_IN", + help = "Save the current flags and their values into a configuration for future use" + )] + pub config_generate: Option, + + #[structopt( + long = "ports-shift", + name = "SHIFT", + help = "Add SHIFT to all port numbers Parity is listening on. Includes network port and all servers (HTTP JSON-RPC, WebSockets JSON-RPC, SecretStore)." + )] + pub ports_shift: Option, +} + +#[derive(StructOpt, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] +pub struct AccountOptions { + #[structopt( + long = "fast-unlock", + name = "FAST_UNLOCK_BOOL", + help = "Use drastically faster unlocking mode. This setting causes raw secrets to be stored unprotected in memory, so use with care." + )] + pub fast_unlock: bool, + + #[structopt( + long = "keys-iterations", + help = "Specify the number of iterations to use when deriving key from the password (bigger is more secure)", + name = "NUM" + )] + pub keys_iterations: Option, + + #[structopt( + long = "accounts-refresh", + help = "Specify the cache time of accounts read from disk. If you manage thousands of accounts set this to 0 to disable refresh.", + name = "TIME" + )] + pub accounts_refresh: Option, + + #[structopt( + long, + help = "Unlock UNLOCK_ACCOUNTS for the duration of the execution. UNLOCK_ACCOUNTS is a comma-delimited list of addresses.", + name = "UNLOCK_ACCOUNTS" + )] + pub unlock: Option, + + #[structopt( + long = "enable-signing-queue", + name = "BOOLEAN", + help = "Enables the signing queue for external transaction signing either via CLI or personal_unlockAccount, turned off by default." + )] + pub enable_signing_queue: bool, + + #[structopt( + long, + name = "FILE", + help = "Provide a file containing a password for unlocking an account. Leading and trailing whitespace is trimmed." + )] + pub password: Vec, // FIXME: Why is this a Vec? +} + +#[derive(StructOpt, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] +pub struct PrivateTransactions { + #[structopt(long = "private-tx-enabled", help = "Enable private transactions.")] + pub private_enabled: bool, + + #[structopt( + long = "private-state-offchain", + help = "Store private state offchain (in the local DB)." + )] + pub private_state_offchain: bool, + + #[structopt( + long = "private-signer", + name = "ACCOUNT", + help = "Specify the account for signing public transaction created upon verified private transaction." + )] + pub private_signer: Option, + + #[structopt( + long = "private-validators", + name = "ACCOUNTS", + help = "Specify the accounts for validating private transactions. ACCOUNTS is a comma-delimited list of addresses." + )] + pub private_validators: Option, + + #[structopt( + long = "private-account", + name = "PRIVATE_ACCOUNT", + help = "Specify the account for signing requests to secret store." + )] + pub private_account: Option, + + #[structopt( + long = "private-sstore-url", + name = "URL", + help = "Specify secret store URL used for encrypting private transactions." + )] + pub private_sstore_url: Option, + + #[structopt( + long = "private-sstore-threshold", + name = "THRESHOLD_NUM", + help = "Specify secret store threshold used for encrypting private transactions." + )] + pub private_sstore_threshold: Option, + + #[structopt( + long = "private-passwords", + name = "PASS_FILE", + help = "Provide a file containing passwords for unlocking accounts (signer, private account, validators)." + )] + pub private_passwords: Option, +} + +#[derive(StructOpt, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] +pub struct UIOptons { + #[structopt( + long = "ui-path", + help = "Specify directory where Trusted UIs tokens should be stored." + )] + pub ui_path: Option, +} + +#[derive(StructOpt, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] +pub struct NetworkingOptions { + #[structopt( + long = "no-warp", + help = "Disable syncing from the snapshot over the network." + )] + pub no_warp: bool, + + #[structopt(long = "no-discovery", help = "Disable new peer discovery.")] + pub no_discovery: bool, + + #[structopt(long = "reserved-only", help = "Connect only to reserved nodes.")] + pub reserved_only: bool, + + #[structopt( + long = "no-ancient-blocks", + help = "Disable downloading old blocks after snapshot restoration or warp sync. Not recommended." + )] + pub no_ancient_blocks: bool, + + #[structopt(long = "no-serve-light", help = "Disable serving of light peers.")] + pub no_serve_light: bool, + + #[structopt( + long = "warp-barrier", + name = "WARP_BARRIER_NUM", + help = "When warp enabled never attempt regular sync before warping to block WARP_BARRIER_NUM." + )] + pub warp_barrier: Option, + + #[structopt( + long, + name = "PORT", + help = "Override the port on which the node should listen." + )] + pub port: Option, + + #[structopt( + long, + name = "IP", + help = "Network interfaces. Valid values are 'all', 'local' or the ip of the interface you want parity to listen to." + )] + pub interface: Option, + + #[structopt( + long = "min-peers", + name = "MIN_NUM", + help = "Try to maintain at least MIN_NUM peers." + )] + pub min_peers: Option, + + #[structopt( + long = "max-peers", + name = "MAX_NUM", + help = "Try to maintain at least MAX_NUM peers." + )] + pub max_peers: Option, + + #[structopt( + long = "snapshot-peers", + name = "SNAPSHOT_NUM", + help = "Allow additional SNAPSHOT_NUM peers for a snapshot sync." + )] + pub snapshot_peers: Option, + + #[structopt( + long, + help = "Specify method to use for determining public address. Must be one of: any, none, upnp, extip:.", + name = "METHOD" + )] + pub nat: Option, + + #[structopt( + long = "allow-ips", + help = "Filter outbound connections. Must 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.", + name = "FILTER" + )] + pub allow_ips: Option, + + #[structopt( + long = "max-pending-peers", + help = "Allow up to PENDING_NUM pending connections.", + name = "PENDING_NUM" + )] + pub max_pending_peers: Option, + + #[structopt( + long = "network-id", + help = "Override the network identifier from the chain we are on.", + name = "INDEX" + )] + pub network_id: Option, + + #[structopt( + long, + name = "BOOTNODES", + help = "Override the bootnodes from our chain. NODES should be comma-delimited enodes." + )] + pub bootnodes: Option, + + #[structopt( + long = "node-key", + name = "NODE_KEY", + help = "Specify node secret key, either as 64-character hex string or input to SHA3 operation." + )] + pub node_key: Option, + + #[structopt( + long = "reserved-peers", + name = "RESERVED_PEERS_FILE", + help = "Provide a file containing enodes, one per line. These nodes will always have a reserved slot on top of the normal maximum peers." + )] + pub reserved_peers: Option, +} + +#[derive(StructOpt, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] +pub struct IPCOptions { + #[structopt( + help = "Provide a file containing enodes, one per line. These nodes will always have a reserved slot on top of the normal maximum peers.", + long = "no-ipc" + )] + pub no_ipc: bool, + + #[structopt( + help = "Provide a file containing enodes, one per line. These nodes will always have a reserved slot on top of the normal maximum peers.", + long = "ipc-path", + name = "IPC_PATH" + )] + pub ipc_path: Option, + + #[structopt( + long = "ipc-chmod", + name = "IPC_CHMOD_NUM", + help = "Specify octal value for ipc socket permissions (unix/bsd only)" + )] + pub ipc_chmod: Option, + + #[structopt( + long = "ipc-apis", + name = "IPC_APIS", + help = "Specify custom API set available via JSON-RPC over IPC using a comma-delimited list of API names. Possible names are: all, safe, web3, net, eth, pubsub, personal, signer, parity, parity_pubsub, parity_accounts, parity_set, traces, rpc, secretstore. You can also disable a specific API by putting '-' in the front, example: all,-personal. 'safe' enables the following APIs: web3, net, eth, pubsub, parity, parity_pubsub, traces, rpc" + )] + pub ipc_apis: Option, +} + +impl IPCOptions { + pub fn ipc_path_default() -> String { + if cfg!(windows) { + r"\\.\pipe\jsonrpc.ipc".to_owned() + } else { + "$BASE/jsonrpc.ipc".to_owned() + } + } +} + +#[derive(StructOpt, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] +pub struct HttpJsonRpcOptions { + #[structopt( + long = "json-rpc-allow-missing-blocks", + help = "RPC calls will return 'null' instead of an error if ancient block sync is still in progress and the block information requested could not be found" + )] + pub jsonrpc_allow_missing_blocks: bool, + + #[structopt(long = "no-jsonrpc", help = "Disable the HTTP JSON-RPC API server.")] + pub no_jsonrpc: bool, + + #[structopt( + long = "jsonrpc-no-keep-alive", + help = "Disable HTTP/1.1 keep alive header. Disabling keep alive will prevent re-using the same TCP connection to fire multiple requests, recommended when using one request per connection." + )] + pub jsonrpc_no_keep_alive: bool, + + #[structopt( + long = "jsonrpc-experimental", + help = "Enable experimental RPCs. Enable to have access to methods from unfinalised EIPs in all namespaces" + )] + pub jsonrpc_experimental: bool, + + #[structopt( + long = "jsonrpc-port", + name = "JSONRPC_PORT", + help = "Specify the port portion of the HTTP JSON-RPC API server." + )] + pub jsonrpc_port: Option, + + #[structopt( + long = "jsonrpc-interface", + name = "JSONRPC_IP", + help = "Specify the hostname portion of the HTTP JSON-RPC API server, JSONRPC_IP should be an interface's IP address, or all (all interfaces) or local." + )] + pub jsonrpc_interface: Option, + + #[structopt( + long = "jsonrpc-apis", + name = "JSONRPC_APIS", + help = "Specify the APIs available through the HTTP JSON-RPC interface using a comma-delimited list of API names. Possible names are: all, safe, debug, web3, net, eth, pubsub, personal, signer, parity, parity_pubsub, parity_accounts, parity_set, traces, rpc, secretstore. You can also disable a specific API by putting '-' in the front, example: all,-personal. 'safe' enables the following APIs: web3, net, eth, pubsub, parity, parity_pubsub, traces, rpc" + )] + pub jsonrpc_apis: Option, + + #[structopt( + long = "jsonrpc-hosts", + name = "JSONRPC_HOSTS", + help = "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\",." + )] + pub jsonrpc_hosts: Option, + + #[structopt( + long = "jsonrpc-server-threads", + name = "JSONRPC_SERVER_THREADS", + help = "Enables multiple threads handling incoming connections for HTTP JSON-RPC server." + )] + pub jsonrpc_server_threads: Option, + + #[structopt( + name = "JSONRPC_CORS_URL", + long = "jsonrpc-cors", + help = "Specify CORS header for HTTP JSON-RPC API responses. Special options: \"all\", \"none\"." + )] + pub jsonrpc_cors: Option, + + #[structopt( + long = "jsonrpc-max-payload", + name = "JSONRPC_MAX_MB", + help = "Specify maximum size for HTTP JSON-RPC requests in megabytes." + )] + pub jsonrpc_max_payload: Option, + + #[structopt( + name = "POLL_LIFETIME_SECS", + long = "poll-lifetime", + help = "Set the RPC filter lifetime to S seconds. The filter has to be polled at least every S seconds , otherwise it is removed." + )] + pub poll_lifetime: Option, +} + +#[derive(StructOpt, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] +pub struct LightClientOptions { + #[structopt( + long = "on-demand-time-window", + help = "Specify the maximum time to wait for a successful response", + name = "RESPONSE_SECS" + )] + pub on_demand_response_time_window: Option, + + #[structopt( + long = "on-demand-start-backoff", + name = "BACKOFF_START_SECS", + help = "Specify light client initial backoff time for a request" + )] + pub on_demand_request_backoff_start: Option, + + #[structopt( + long = "on-demand-end-backoff", + name = "BACKOFF_END_SECS", + help = "Specify light client maximam backoff time for a request" + )] + pub on_demand_request_backoff_max: Option, + + #[structopt( + long = "on-demand-max-backoff-rounds", + name = "BACKOFF_MAX_ROUNDS_TIMES", + help = "Specify light client maximam number of backoff iterations for a request" + )] + pub on_demand_request_backoff_rounds_max: Option, + + #[structopt( + long = "on-demand-consecutive-failures", + name = "MAX_CONSECUTIVE_FAILURE_TIMES", + help = "Specify light client the number of failures for a request until it gets exponentially backed off" + )] + pub on_demand_request_consecutive_failures: Option, +} + +#[derive(StructOpt, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] +pub struct WebsocketsOptions { + #[structopt(help = "Disable the WebSockets JSON-RPC server.", long = "no-ws")] + pub no_ws: bool, + + #[structopt( + long = "ws-port", + name = "WS_PORT", + help = "Specify the port portion of the WebSockets JSON-RPC server." + )] + pub ws_port: Option, + + #[structopt( + long = "ws-interface", + name = "WS_INTERFACE_IP", + help = "Specify the hostname portion of the WebSockets JSON-RPC server, IP should be an interface's IP address, or all (all interfaces) or local." + )] + pub ws_interface: Option, + + #[structopt( + help = "Specify the JSON-RPC APIs available through the WebSockets interface using a comma-delimited list of API names. Possible names are: all, safe, web3, net, eth, pubsub, personal, signer, parity, parity_pubsub, parity_accounts, parity_set, traces, rpc, secretstore. You can also disable a specific API by putting '-' in the front, example: all,-personal. 'safe' enables the following APIs: web3, net, eth, pubsub, parity, parity_pubsub, traces, rpc", + long = "ws-apis", + name = "WS_APIS" + )] + pub ws_apis: Option, + + #[structopt( + help = "Specify Origin header values allowed to connect. Special options: \"all\", \"none\".", + long = "ws-origins", + name = "WS_ORIGINS_URL" + )] + pub ws_origins: Option, + + #[structopt( + help = "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\".", + long = "ws-hosts", + name = "WS_HOSTS" + )] + pub ws_hosts: Option, + + #[structopt( + help = "Maximum number of allowed concurrent WebSockets JSON-RPC connections.", + long = "ws-connections", + name = "WS_MAX_CONN" + )] + pub ws_max_connections: Option, +} + +#[derive(StructOpt, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] +pub struct SecretStoreOptions { + #[structopt(help = "Disable Secret Store functionality.", long = "no-secretstore")] + pub no_secretstore: bool, + + #[structopt(help = "Disable Secret Store HTTP API.", long = "no-secretstore-http")] + pub no_secretstore_http: bool, + + #[structopt( + help = "Do not run servers set change session automatically when servers set changes. This option has no effect when servers set is read from configuration file.", + long = "no-secretstore-auto-migrate" + )] + pub no_secretstore_auto_migrate: bool, + + #[structopt( + name = "HTTP_CORS_URLS", + help = "Specify CORS header for Secret Store HTTP API responses. Special options: \"all\", \"none\".", + long = "secretstore-http-cors" + )] + pub secretstore_http_cors: Option, + + #[structopt( + help = "Secret Store permissioning contract address source: none, registry (contract address is read from 'secretstore_acl_checker' entry in registry) or address.", + long = "secretstore-acl-contract" + )] + pub secretstore_acl_contract: Option, + + #[structopt( + long = "secrestore-contract", + name = "SECRETSTORE_SOURCE", + help = "Secret Store Service contract address source: none, registry (contract address is read from 'secretstore_service' entry in registry) or address." + )] + pub secretstore_contract: Option, + + #[structopt( + long = "secretstore-srv-gen-contract", + name = "GEN_SOURCE", + help = "Secret Store Service server key generation contract address source: none, registry (contract address is read from 'secretstore_service_srv_gen' entry in registry) or address." + )] + pub secretstore_srv_gen_contract: Option, + + #[structopt( + help = "Secret Store Service server key retrieval contract address source: none, registry (contract address is read from 'secretstore_service_srv_retr' entry in registry) or address.", + name = "RETR_SOURCE", + long = "secretstore-srv-retr-contract" + )] + pub secretstore_srv_retr_contract: Option, + + #[structopt( + help = "Secret Store Service document key store contract address source: none, registry (contract address is read from 'secretstore_service_doc_store' entry in registry) or address.", + name = "DOC_STORE_SOURCE", + long = "secretstore-doc-store-contract" + )] + pub secretstore_doc_store_contract: Option, + + #[structopt( + help = "Secret Store Service document key shadow retrieval contract address source: none, registry (contract address is read from 'secretstore_service_doc_sretr' entry in registry) or address.", + name = "DOC_SRETR_SOURCE", + long = "secretstore-doc-sretr-contract" + )] + pub secretstore_doc_sretr_contract: Option, + + #[structopt( + help = "Comma-separated list of other secret store cluster nodes in form NODE_PUBLIC_KEY_IN_HEX@NODE_IP_ADDR:NODE_PORT.", + name = "SECRETSTORE_NODES", + long = "secretstore-nodes" + )] + pub secretstore_nodes: Option, + + #[structopt( + name = "SET_CONTRACT_SOURCE", + long = "secretstore-server-set-contract", + help = "Secret Store server set contract address source: none, registry (contract address is read from 'secretstore_server_set' entry in registry) or address." + )] + pub secretstore_server_set_contract: Option, + + #[structopt( + help = "Specify the hostname portion for listening to Secret Store Key Server internal requests, IP should be an interface's IP address, or local.", + name = "SECRETSTORE_IP", + long = "secretstore-interface-ip" + )] + pub secretstore_interface: Option, + + #[structopt( + long = "secretstore-port", + name = "SECRETSTORE_PORT", + help = "Specify the port portion for listening to Secret Store Key Server internal requests." + )] + pub secretstore_port: Option, + + #[structopt( + long = "secretstore-http-interface", + help = "Specify the hostname portion for listening to Secret Store Key Server HTTP requests, IP should be an interface's IP address, or local.", + name = "SECRETSTORE_HTTP_INTERFACE" + )] + pub secretstore_http_interface: Option, + + #[structopt( + long = "secretstore-http-port", + name = "SECRETSTORE_HTTP_PORT", + help = "Specify the port portion for listening to Secret Store Key Server HTTP requests." + )] + pub secretstore_http_port: Option, + + #[structopt( + name = "SECRETSTORE_PATH", + long = "secretstore-path", + help = "Specify directory where Secret Store should save its data." + )] + pub secretstore_path: Option, + + #[structopt( + long = "secretstore-secret", + name = "SECRETSTORE_SECRET", + help = "Hex-encoded secret key of this node." + )] + pub secretstore_secret: Option, + + #[structopt( + long = "secretstore-admin-public", + name = "SECRETSTORE_ADMIN_PUBLIC", + help = "Hex-encoded public key of secret store administrator." + )] + pub secretstore_admin_public: Option, +} + +#[derive(StructOpt, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] +pub struct SealingMiningOptions { + #[structopt( + help = "Force the node to author new blocks as if it were always sealing/mining.", + long = "force-sealing" + )] + pub force_sealing: bool, + + #[structopt( + help = "Force the node to author new blocks when a new uncle block is imported.", + long = "reseal-on-uncle" + )] + pub reseal_on_uncle: bool, + + #[structopt( + help = "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.", + long = "remove-solved" + )] + pub remove_solved: bool, + + #[structopt( + help = "Local transactions sent through JSON-RPC (HTTP, WebSockets, etc) will be treated as 'external' if the sending account is unknown.", + long = "tx-queue-no-unfamiliar-locals" + )] + pub tx_queue_no_unfamiliar_locals: bool, + + #[structopt( + help = "Disables transaction queue optimization to early reject transactions below minimal effective gas price. This allows local transactions to always enter the pool, despite it being full, but requires additional ecrecover on every transaction.", + long = "tx-queue-no-early-reject" + )] + pub tx_queue_no_early_reject: bool, + + #[structopt( + help = "Always refuse service transactions.", + long = "refuse-service-transactions" + )] + pub refuse_service_transactions: bool, + + #[structopt( + help = "Pending block will be created with maximal possible gas limit and will execute all transactions in the queue. Note that such block is invalid and should never be attempted to be mined.", + long = "infinite-pending-block" + )] + pub infinite_pending_block: bool, + + #[structopt( + help = "Don't save pending local transactions to disk to be restored whenever the node restarts.", + long = "no-persistent-txqueue" + )] + pub no_persistent_txqueue: bool, + + // For backward compatibility; Stratum should be enabled if the config file + // contains a `[stratum]` section and it is not explicitly disabled (disable = true) + #[structopt(help = "Run Stratum server for miner push notification.", long)] + pub stratum: bool, + + #[structopt( + long = "reseal-on-txs", + name = "RESEAL_TXS_SET", + help = "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." + )] + pub reseal_on_txs: Option, + + #[structopt( + help = "Specify the minimum time between reseals from incoming transactions. MS is time measured in milliseconds.", + long = "reseal-min-period", + name = "RESEAL_MIN_MS" + )] + pub reseal_min_period: Option, + + #[structopt( + long = "reseal-max-period", + name = "RESEAL_MAX_MS", + help = "Specify the maximum time between reseals from incoming transactions. MS is time measured in milliseconds." + )] + pub reseal_max_period: Option, + + #[structopt( + name = "WORK_QUEUE_SIZE_ITEMS", + long = "work-queue-size", + help = "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." + )] + pub work_queue_size: Option, + + #[structopt( + long = "relay-set", + name = "RELAY_SET", + help = "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." + )] + pub relay_set: Option, + + #[structopt( + long = "usd-per-tx", + name = "USD_PER_TX", + help = "Amount of USD to be paid for a basic transaction. The minimum gas price is set accordingly." + )] + pub usd_per_tx: Option, + + #[structopt( + help = "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.", + name = "USD_PER_ETH_SOURCE", + long = "usd-per-eth" + )] + pub usd_per_eth: Option, + + #[structopt( + long = "price-update-period", + name = "PRICE_UPDATE_T", + help = "PRICE_UPDATE_T will be allowed to pass between each gas price update. PRICE_UPDATE_T may be daily, hourly, a number of seconds, or a time string of the form \"2 days\", \"30 minutes\" etc.." + )] + pub price_update_period: Option, + + #[structopt( + help = "Amount of gas per block to target when sealing a new block.", + long = "gas-floor-target", + name = "GAS_FLOOR" + )] + pub gas_floor_target: Option, + + #[structopt( + help = "A cap on how large we will raise the gas limit per block due to transaction volume.", + long = "gas-cap", + name = "GAS_CAP" + )] + pub gas_cap: Option, + + #[structopt( + help = "Maximum amount of memory that can be used by the transaction queue. Setting this parameter to 0 disables limiting.", + long = "tx-queue-mem-limit", + name = "TX_QUEUE_LIMIT_MB" + )] + pub tx_queue_mem_limit: Option, + + #[structopt( + help = "Maximum amount of transactions in the queue (waiting to be included in next block).", + long = "tx-queue-size", + name = "TX_QUEUE_SIZE_LIMIT" + )] + pub tx_queue_size: Option, + + #[structopt( + help = "Maximum number of transactions per sender in the queue. By default it's 1% of the entire queue, but not less than 16.", + long = "tx-queue-per-sender", + name = "TX_QUEUE_PER_SENDER_LIMIT" + )] + pub tx_queue_per_sender: Option, + + #[structopt( + help = "Specify local accounts for which transactions are prioritized in the queue. ACCOUNTS is a comma-delimited list of addresses.", + long = "tx-queue-locals", + name = "TX_QUEUE_LOCAL_ACCOUNTS" + )] + pub tx_queue_locals: Option, + + #[structopt( + help = "Prioritization strategy used to order transactions in the queue. S may be: gas_price - Prioritize txs with high gas price", + long = "tx-queue-strategy", + name = "TX_QUEUE_S" + )] + pub tx_queue_strategy: Option, + + #[structopt( + help = "Interface address for Stratum server.", + long = "stratum-interface", + name = "STRATUM_IP" + )] + pub stratum_interface: Option, + + #[structopt( + help = "Port for Stratum server to listen on.", + long = "stratum-port", + name = "STRATUM_PORT" + )] + pub stratum_port: Option, + + #[structopt( + help = "Minimum amount of Wei per GAS to be paid for a transaction to be accepted for mining. Overrides --usd-per-tx.", + long = "min-gas-price", + name = "MIN_GAS_PRICE_STRING" + )] + pub min_gas_price: Option, + + #[structopt( + help = "Set PCT percentile gas price value from last 100 blocks as default gas price when sending transactions.", + long = "gas-price-percentile", + name = "PCT" + )] + pub gas_price_percentile: Option, + + #[structopt( + help = "Specify the block author (aka \"coinbase\") address for sending block rewards from sealed blocks. NOTE: MINING WILL NOT WORK WITHOUT THIS OPTION.", + long, + name = "ADDRESS" + )] + pub author: Option, // Sealing / Mining Option + + #[structopt( + help = "Specify the address which should be used to sign consensus messages and issue blocks. Relevant only to non-PoW chains.", + long = "engine-signer", + name = "ENGINE_SIGNER_ADDRESS" + )] + pub engine_signer: Option, + + #[structopt( + help = "Apply a limit of GAS as the maximum amount of gas a single transaction may have for it to be mined.", + long = "tx-gas-limit", + name = "TX_GAS_LIMIT" + )] + pub tx_gas_limit: Option, + + #[structopt( + help = "Maximal time for processing single transaction. If enabled senders of transactions offending the limit will get other transactions penalized.", + long = "tx-time-limit", + name = "TX_TIME_LIMIT_MS" + )] + pub tx_time_limit: Option, + + #[structopt( + long = "extra-data", + help = "Specify a custom extra-data for authored blocks, no more than 32 characters.", + name = "EXTRA_DATA_STRING" + )] + pub extra_data: Option, + + #[structopt( + name = "NOTIFY_WORK_URLS", + help = "URLs to which work package notifications are pushed. URLS should be a comma-delimited list of HTTP URLs.", + long = "notify-work" + )] + pub notify_work: Option, + + #[structopt( + name = "STARTUM_SECRET_STRING", + long = "stratum-secret", + help = "Secret for authorizing Stratum server for peers." + )] + pub stratum_secret: Option, + + #[structopt( + long = "max-round-blocks-to-import", + name = "MAX_ROUND_BLOCKS_S", + help = "Maximal number of blocks to import for each import round." + )] + pub max_round_blocks_to_import: Option, +} + +#[derive(StructOpt, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] +pub struct InternalOptions { + #[structopt( + long = "can-restart", + help = "Executable will auto-restart if exiting with 69" + )] + pub can_restart: bool, +} + +#[derive(StructOpt, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] +pub struct MiscellaneousOptions { + #[structopt(help = "Don't use terminal color codes in output.", long = "no-color")] + pub no_color: bool, + + // version flag is automatically provided by structopt + #[structopt(long = "no-config", help = "Don't load a configuration file.")] + pub no_config: bool, + + #[structopt( + short = "l", + long, + name = "LOGGING", + help = "Specify the general logging level (error, warn, info, debug or trace). It can also be set for a specific module, example: '-l sync=debug,rpc=trace'" + )] + pub logging: Option, + + #[structopt( + long = "log-file", + name = "LOG_FILENAME", + help = "Specify a filename into which logging should be appended" + )] + pub log_file: Option, +} + +#[derive(StructOpt, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] +pub struct FootPrintOptions { + #[structopt( + help = "Automatically scale amount of verifier threads based on workload. Not guaranteed to be faster.", + long = "scale-verifiers" + )] + pub scale_verifiers: bool, + + #[structopt( + help = "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).", + long, + name = "TRACING_BOOL" + )] + pub tracing: Option, + + #[structopt( + long, + name = "PRUNING_METHOD", + help = "Configure pruning of the state/storage trie. PRUNING_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." + )] + pub pruning: Option, + + #[structopt( + long = "pruning-history", + help = "Set a minimum number of recent states to keep in memory when pruning is active.", + name = "PRUNING_HISTORY_NUM" + )] + pub pruning_history: Option, + + #[structopt( + long = "pruning-memory", + name = "PRUNING_MEMORY_MB", + help = "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." + )] + pub pruning_memory: Option, + + #[structopt( + help = "Override database cache size.", + long = "cache-size-db", + name = "CACHE_SIZE_DB_MB" + )] + pub cache_size_db: Option, + + #[structopt( + help = "Specify the preferred size of the blockchain cache in megabytes.", + long = "cache-size-blocks", + name = "CACHE_SIZE_BLOCKS_MB" + )] + pub cache_size_blocks: Option, + + #[structopt( + help = "Specify the maximum size of memory to use for block queue.", + long = "cache-size-queue", + name = "CACHE_SIZE_QUEUE_MB" + )] + pub cache_size_queue: Option, + + #[structopt( + help = "Specify the maximum size of memory to use for the state cache.", + long = "cache-size-state", + name = "CACHE_SIZE_STATE" + )] + pub cache_size_state: Option, + + #[structopt( + help = "Database compaction type. TYPE may be one of: ssd - suitable for SSDs and fast HDDs; hdd - suitable for slow HDDs; auto - determine automatically.", + long = "db-compaction", + name = "DB_COMPACTION_TYPE" + )] + pub db_compaction: Option, + + #[structopt( + help = "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.", + long = "fat-db", + name = "FAT_DB_BOOL" + )] + pub fat_db: Option, + + #[structopt( + help = "Set total amount of discretionary memory to use for the entire system, overrides other cache and queue options.", + long = "cache-size", + name = "CACHE_SIZE_MB" + )] + pub cache_size: Option, + + #[structopt( + help = "Amount of verifier threads to use or to begin with, if verifier auto-scaling is enabled.", + name = "NUM_VERIFIERS_INT", + long = "num-verifiers" + )] + pub num_verifiers: Option, +} + +#[derive(StructOpt, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] +pub struct ImportExportOptions { + #[structopt(long = "no-seal-check", help = "Skip block seal check.")] + pub no_seal_check: bool, +} + +#[derive(StructOpt, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] +pub struct SnapshotOptions { + #[structopt( + help = "Disable automated snapshots which usually occur once every 5000 blocks.", + long = "no-periodic-snapshots" + )] + pub no_periodic_snapshot: bool, + + #[structopt( + help = "Enables multiple threads for snapshots creation.", + long = "snapshot-threads", + name = "SNAPSHOT_THREADS_NUM" + )] + pub snapshot_threads: Option, +} + +#[derive(StructOpt, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] +pub struct LegacyOptions { + // TODO: These options were hidden from config, so should we not include them? + #[structopt( + long, + help = "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." + )] + pub geth: bool, + + #[structopt( + help = "Attempt to import keys from Geth client.", + long = "import-geth-keys" + )] + pub import_geth_keys: bool, +} diff --git a/parity/cli/mod.rs b/parity/cli/mod.rs index 6fa642deece..c79a0d6d232 100644 --- a/parity/cli/mod.rs +++ b/parity/cli/mod.rs @@ -14,2199 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Open Ethereum. If not, see . -#[macro_use] -mod usage; -mod presets; - -use std::collections::HashSet; -use super::helpers; - -usage! { - { - // CLI subcommands - // Subcommands must start with cmd_ and have '_' in place of '-' - // Sub-subcommands must start with the name of the subcommand - // Arguments must start with arg_ - // Flags must start with flag_ - - CMD cmd_daemon - { - "Use Parity as a daemon", - - ARG arg_daemon_pid_file: (Option) = None, - "", - "Path to the pid file", - } - - CMD cmd_account - { - "Manage accounts", - - CMD cmd_account_new { - "Create a new account (and its associated key) for the given --chain (default: mainnet)", - } - - CMD cmd_account_list { - "List existing accounts of the given --chain (default: mainnet)", - } - - CMD cmd_account_import - { - "Import accounts from JSON UTC keystore files to the specified --chain (default mainnet)", - - ARG arg_account_import_path : (Option>) = None, - "...", - "Path to the accounts", - } - } - - CMD cmd_wallet - { - "Manage wallet", - - CMD cmd_wallet_import - { - "Import wallet into the given --chain (default: mainnet)", - - ARG arg_wallet_import_path: (Option) = None, - "", - "Path to the wallet", - } - } - - CMD cmd_import - { - "Import blockchain data from a file to the given --chain database (default: mainnet)", - - ARG arg_import_format: (Option) = None, - "--format=[FORMAT]", - "Import in a given format. FORMAT must be either 'hex' or 'binary'. (default: auto)", - - ARG arg_import_file: (Option) = None, - "[FILE]", - "Path to the file to import from", - } - - CMD cmd_export - { - "Export blockchain", - - CMD cmd_export_blocks - { - "Export the blockchain blocks from the given --chain database (default: mainnet) into a file. This command requires the chain to be synced with --fat-db on.", - - ARG arg_export_blocks_format: (Option) = None, - "--format=[FORMAT]", - "Export in a given format. FORMAT must be either 'hex' or 'binary'. (default: binary)", - - ARG arg_export_blocks_from: (String) = "1", - "--from=[BLOCK]", - "Export from block BLOCK, which may be an index or hash.", - - ARG arg_export_blocks_to: (String) = "latest", - "--to=[BLOCK]", - "Export to (including) block BLOCK, which may be an index, hash or latest.", - - ARG arg_export_blocks_file: (Option) = None, - "[FILE]", - "Path to the exported file", - } - - CMD cmd_export_state - { - "Export the blockchain state from the given --chain (default: mainnet) into a file. This command requires the chain to be synced with --fat-db on.", - - FLAG flag_export_state_no_storage: (bool) = false, - "--no-storage", - "Don't export account storage.", - - FLAG flag_export_state_no_code: (bool) = false, - "--no-code", - "Don't export account code.", - - ARG arg_export_state_min_balance: (Option) = None, - "--min-balance=[WEI]", - "Don't export accounts with balance less than specified.", - - ARG arg_export_state_max_balance: (Option) = None, - "--max-balance=[WEI]", - "Don't export accounts with balance greater than specified.", - - ARG arg_export_state_at: (String) = "latest", - "--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", - - ARG arg_export_state_format: (Option) = None, - "--format=[FORMAT]", - "Export in a given format. FORMAT must be either 'hex' or 'binary'. (default: binary)", - - ARG arg_export_state_file: (Option) = None, - "[FILE]", - "Path to the exported file", - } - } - - CMD cmd_signer - { - "Manage signer", - - CMD cmd_signer_new_token { - "Generate a new signer-authentication token for the given --chain (default: mainnet)", - } - - CMD cmd_signer_list { - "List the signer-authentication tokens from given --chain (default: mainnet)", - } - - CMD cmd_signer_sign - { - "Sign", - - ARG arg_signer_sign_id: (Option) = None, - "[ID]", - "ID", - } - - CMD cmd_signer_reject - { - "Reject", - - ARG arg_signer_reject_id: (Option) = None, - "", - "ID", - } - } - - CMD cmd_snapshot - { - "Make a snapshot of the database of the given --chain (default: mainnet)", - - ARG arg_snapshot_at: (String) = "latest", - "--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", - - ARG arg_snapshot_file: (Option) = None, - "", - "Path to the file to export to", - } - - CMD cmd_restore - { - "Restore the database of the given --chain (default: mainnet) from a snapshot file", - - ARG arg_restore_file: (Option) = None, - "[FILE]", - "Path to the file to restore from", - } - - CMD cmd_tools - { - "Tools", - - CMD cmd_tools_hash - { - "Hash a file using the Keccak-256 algorithm", - - ARG arg_tools_hash_file: (Option) = None, - "", - "File", - } - } - - CMD cmd_db - { - "Manage the database representing the state of the blockchain on this system", - - CMD cmd_db_kill { - "Clean the database of the given --chain (default: mainnet)", - } - - CMD cmd_db_reset { - "Removes NUM latests blocks from the db", - - ARG arg_db_reset_num: (u32) = 10u32, - "", - "Number of blocks to revert", - } - - } - - CMD cmd_export_hardcoded_sync - { - "Print the hashed light clients headers of the given --chain (default: mainnet) in a JSON format. To be used as hardcoded headers in a genesis file.", - } - - // CMD removed in 2.0 - - CMD cmd_dapp - { - "Manage dapps", - - ARG arg_dapp_path: (Option) = None, - "", - "Path to the dapps", - } - } - { - // Global flags and arguments - ["Operating Options"] - FLAG flag_no_download: (bool) = false, or |c: &Config| c.parity.as_ref()?.no_download.clone(), - "--no-download", - "Normally new releases will be downloaded ready for updating. This disables it. Not recommended.", - - FLAG flag_no_consensus: (bool) = false, or |c: &Config| c.parity.as_ref()?.no_consensus.clone(), - "--no-consensus", - "Force the binary to run even if there are known issues regarding consensus. Not recommended.", - - FLAG flag_light: (bool) = false, or |c: &Config| c.parity.as_ref()?.light, - "--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.", - - FLAG flag_no_hardcoded_sync: (bool) = false, or |c: &Config| c.parity.as_ref()?.no_hardcoded_sync, - "--no-hardcoded-sync", - "By default, if there is no existing database the light client will automatically jump to a block hardcoded in the chain's specifications. This disables this feature.", - - FLAG flag_force_direct: (bool) = false, or |_| None, - "--force-direct", - "Run the originally installed version of Parity, ignoring any updates that have since been installed.", - - ARG arg_mode: (String) = "last", or |c: &Config| c.parity.as_ref()?.mode.clone(), - "--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 JSON-RPC is active; offline - Parity doesn't sync.", - - ARG arg_mode_timeout: (u64) = 300u64, or |c: &Config| c.parity.as_ref()?.mode_timeout.clone(), - "--mode-timeout=[SECS]", - "Specify the number of seconds before inactivity timeout occurs when mode is dark or passive", - - ARG arg_mode_alarm: (u64) = 3600u64, or |c: &Config| c.parity.as_ref()?.mode_alarm.clone(), - "--mode-alarm=[SECS]", - "Specify the number of seconds before auto sleep reawake timeout occurs when mode is passive", - - ARG arg_auto_update: (String) = "critical", or |c: &Config| c.parity.as_ref()?.auto_update.clone(), - "--auto-update=[SET]", - "Set a releases set to automatically update and install. SET can be one of: all - All updates in the our release track; critical - Only consensus/security updates; none - No updates will be auto-installed.", - - ARG arg_auto_update_delay: (u16) = 100u16, or |c: &Config| c.parity.as_ref()?.auto_update_delay.clone(), - "--auto-update-delay=[NUM]", - "Specify the maximum number of blocks used for randomly delaying updates.", - - ARG arg_auto_update_check_frequency: (u16) = 20u16, or |c: &Config| c.parity.as_ref()?.auto_update_check_frequency.clone(), - "--auto-update-check-frequency=[NUM]", - "Specify the number of blocks between each auto-update check.", - - ARG arg_release_track: (String) = "current", or |c: &Config| c.parity.as_ref()?.release_track.clone(), - "--release-track=[TRACK]", - "Set which release track we should use for updates. TRACK can be one of: stable - Stable releases; nightly - Nightly releases (unstable); testing - Testing releases (do not use); current - Whatever track this executable was released on.", - - ARG arg_chain: (String) = "foundation", or |c: &Config| c.parity.as_ref()?.chain.clone(), - "--chain=[CHAIN]", - "Specify the blockchain type. CHAIN may be either a JSON chain specification file or ethereum, classic, classic-no-phoenix, poacore, xdai, volta, ewc, musicoin, ellaism, mix, callisto, ethercore, mordor, ropsten, kovan, rinkeby, goerli, kotti, poasokol, testnet, evantestcore, evancore or dev.", - - ARG arg_keys_path: (String) = "$BASE/keys", or |c: &Config| c.parity.as_ref()?.keys_path.clone(), - "--keys-path=[PATH]", - "Specify the path for JSON key files to be found", - - ARG arg_identity: (String) = "", or |c: &Config| c.parity.as_ref()?.identity.clone(), - "--identity=[NAME]", - "Specify your node's name.", - - ARG arg_base_path: (Option) = None, or |c: &Config| c.parity.as_ref()?.base_path.clone(), - "-d, --base-path=[PATH]", - "Specify the base data storage path.", - - ARG arg_db_path: (Option) = None, or |c: &Config| c.parity.as_ref()?.db_path.clone(), - "--db-path=[PATH]", - "Specify the database directory path", - - ARG arg_sync_until: (Option) = None, or |c: &Config| c.parity.as_ref()?.sync_until.clone(), - "--sync-until=[NUM]", - "Sync until the given block has been imported, then enter offline mode. Intended for debug/benchmarking only.", - - ["Convenience Options"] - FLAG flag_unsafe_expose: (bool) = false, or |c: &Config| c.misc.as_ref()?.unsafe_expose, - "--unsafe-expose", - "All servers will listen on external interfaces and will be remotely accessible. It's equivalent with setting the following: --[ws,jsonrpc,secretstore,stratum,dapps,secretstore-http]-interface=all --*-hosts=all This option is UNSAFE and should be used with great care!", - - ARG arg_config: (String) = "$BASE/config.toml", or |_| None, - "-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.", - - ARG arg_ports_shift: (u16) = 0u16, or |c: &Config| c.misc.as_ref()?.ports_shift, - "--ports-shift=[SHIFT]", - "Add SHIFT to all port numbers Parity is listening on. Includes network port and all servers (HTTP JSON-RPC, WebSockets JSON-RPC, SecretStore).", - - ["Account Options"] - FLAG flag_fast_unlock: (bool) = false, or |c: &Config| c.account.as_ref()?.fast_unlock.clone(), - "--fast-unlock", - "Use drastically faster unlocking mode. This setting causes raw secrets to be stored unprotected in memory, so use with care.", - - ARG arg_keys_iterations: (u32) = 10240u32, or |c: &Config| c.account.as_ref()?.keys_iterations.clone(), - "--keys-iterations=[NUM]", - "Specify the number of iterations to use when deriving key from the password (bigger is more secure)", - - ARG arg_accounts_refresh: (u64) = 5u64, or |c: &Config| c.account.as_ref()?.refresh_time.clone(), - "--accounts-refresh=[TIME]", - "Specify the cache time of accounts read from disk. If you manage thousands of accounts set this to 0 to disable refresh.", - - ARG arg_unlock: (Option) = None, or |c: &Config| c.account.as_ref()?.unlock.as_ref().map(|vec| vec.join(",")), - "--unlock=[ACCOUNTS]", - "Unlock ACCOUNTS for the duration of the execution. ACCOUNTS is a comma-delimited list of addresses.", - - ARG arg_enable_signing_queue: (bool) = false, or |c: &Config| c.account.as_ref()?.enable_signing_queue, - "--enable-signing-queue=[BOOLEAN]", - "Enables the signing queue for external transaction signing either via CLI or personal_unlockAccount, turned off by default.", - - ARG arg_password: (Vec) = Vec::new(), or |c: &Config| c.account.as_ref()?.password.clone(), - "--password=[FILE]...", - "Provide a file containing a password for unlocking an account. Leading and trailing whitespace is trimmed.", - - ["Private Transactions Options"] - FLAG flag_private_enabled: (bool) = false, or |c: &Config| c.private_tx.as_ref()?.enabled, - "--private-tx-enabled", - "Enable private transactions.", - - FLAG flag_private_state_offchain: (bool) = false, or |c: &Config| c.private_tx.as_ref()?.state_offchain, - "--private-state-offchain", - "Store private state offchain (in the local DB).", - - ARG arg_private_signer: (Option) = None, or |c: &Config| c.private_tx.as_ref()?.signer.clone(), - "--private-signer=[ACCOUNT]", - "Specify the account for signing public transaction created upon verified private transaction.", - - ARG arg_private_validators: (Option) = None, or |c: &Config| c.private_tx.as_ref()?.validators.as_ref().map(|vec| vec.join(",")), - "--private-validators=[ACCOUNTS]", - "Specify the accounts for validating private transactions. ACCOUNTS is a comma-delimited list of addresses.", - - ARG arg_private_account: (Option) = None, or |c: &Config| c.private_tx.as_ref()?.account.clone(), - "--private-account=[ACCOUNT]", - "Specify the account for signing requests to secret store.", - - ARG arg_private_sstore_url: (Option) = None, or |c: &Config| c.private_tx.as_ref()?.sstore_url.clone(), - "--private-sstore-url=[URL]", - "Specify secret store URL used for encrypting private transactions.", - - ARG arg_private_sstore_threshold: (Option) = None, or |c: &Config| c.private_tx.as_ref()?.sstore_threshold.clone(), - "--private-sstore-threshold=[NUM]", - "Specify secret store threshold used for encrypting private transactions.", - - ARG arg_private_passwords: (Option) = None, or |c: &Config| c.private_tx.as_ref()?.passwords.clone(), - "--private-passwords=[FILE]...", - "Provide a file containing passwords for unlocking accounts (signer, private account, validators).", - - ["UI Options"] - ARG arg_ui_path: (String) = "$BASE/signer", or |c: &Config| c.ui.as_ref()?.path.clone(), - "--ui-path=[PATH]", - "Specify directory where Trusted UIs tokens should be stored.", - - ["Networking Options"] - FLAG flag_no_warp: (bool) = false, or |c: &Config| c.network.as_ref()?.warp.clone().map(|w| !w), - "--no-warp", - "Disable syncing from the snapshot over the network.", - - FLAG flag_no_discovery: (bool) = false, or |c: &Config| c.network.as_ref()?.discovery.map(|d| !d).clone(), - "--no-discovery", - "Disable new peer discovery.", - - FLAG flag_reserved_only: (bool) = false, or |c: &Config| c.network.as_ref()?.reserved_only.clone(), - "--reserved-only", - "Connect only to reserved nodes.", - - FLAG flag_no_ancient_blocks: (bool) = false, or |_| None, - "--no-ancient-blocks", - "Disable downloading old blocks after snapshot restoration or warp sync. Not recommended.", - - FLAG flag_no_serve_light: (bool) = false, or |c: &Config| c.network.as_ref()?.no_serve_light.clone(), - "--no-serve-light", - "Disable serving of light peers.", - - ARG arg_warp_barrier: (Option) = None, or |c: &Config| c.network.as_ref()?.warp_barrier.clone(), - "--warp-barrier=[NUM]", - "When warp enabled never attempt regular sync before warping to block NUM.", - - ARG arg_port: (u16) = 30303u16, or |c: &Config| c.network.as_ref()?.port.clone(), - "--port=[PORT]", - "Override the port on which the node should listen.", - - ARG arg_interface: (String) = "all", or |c: &Config| c.network.as_ref()?.interface.clone(), - "--interface=[IP]", - "Network interfaces. Valid values are 'all', 'local' or the ip of the interface you want parity to listen to.", - - ARG arg_min_peers: (Option) = None, or |c: &Config| c.network.as_ref()?.min_peers.clone(), - "--min-peers=[NUM]", - "Try to maintain at least NUM peers.", - - ARG arg_max_peers: (Option) = None, or |c: &Config| c.network.as_ref()?.max_peers.clone(), - "--max-peers=[NUM]", - "Allow up to NUM peers.", - - ARG arg_snapshot_peers: (u16) = 0u16, or |c: &Config| c.network.as_ref()?.snapshot_peers.clone(), - "--snapshot-peers=[NUM]", - "Allow additional NUM peers for a snapshot sync.", - - ARG arg_nat: (String) = "any", or |c: &Config| c.network.as_ref()?.nat.clone(), - "--nat=[METHOD]", - "Specify method to use for determining public address. Must be one of: any, none, upnp, extip:.", - - ARG arg_allow_ips: (String) = "all", or |c: &Config| c.network.as_ref()?.allow_ips.clone(), - "--allow-ips=[FILTER]", - "Filter outbound connections. Must 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.", - - ARG arg_max_pending_peers: (u16) = 64u16, or |c: &Config| c.network.as_ref()?.max_pending_peers.clone(), - "--max-pending-peers=[NUM]", - "Allow up to NUM pending connections.", - - ARG arg_network_id: (Option) = None, or |c: &Config| c.network.as_ref()?.id.clone(), - "--network-id=[INDEX]", - "Override the network identifier from the chain we are on.", - - ARG arg_bootnodes: (Option) = None, or |c: &Config| c.network.as_ref()?.bootnodes.as_ref().map(|vec| vec.join(",")), - "--bootnodes=[NODES]", - "Override the bootnodes from our chain. NODES should be comma-delimited enodes.", - - ARG arg_node_key: (Option) = None, or |c: &Config| c.network.as_ref()?.node_key.clone(), - "--node-key=[KEY]", - "Specify node secret key, either as 64-character hex string or input to SHA3 operation.", - - ARG arg_reserved_peers: (Option) = None, or |c: &Config| c.network.as_ref()?.reserved_peers.clone(), - "--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.", - - CHECK |args: &Args| { - if let (Some(max_peers), Some(min_peers)) = (args.arg_max_peers, args.arg_min_peers) { - if min_peers > max_peers { - return Err(ArgsError::PeerConfiguration); - } - } - - Ok(()) - }, - - ["API and Console Options – HTTP JSON-RPC"] - FLAG flag_jsonrpc_allow_missing_blocks: (bool) = false, or |c: &Config| c.rpc.as_ref()?.allow_missing_blocks.clone(), - "--jsonrpc-allow-missing-blocks", - "RPC calls will return 'null' instead of an error if ancient block sync is still in progress and the block information requested could not be found", - - FLAG flag_no_jsonrpc: (bool) = false, or |c: &Config| c.rpc.as_ref()?.disable.clone(), - "--no-jsonrpc", - "Disable the HTTP JSON-RPC API server.", - - FLAG flag_jsonrpc_no_keep_alive: (bool) = false, or |c: &Config| c.rpc.as_ref()?.keep_alive, - "--jsonrpc-no-keep-alive", - "Disable HTTP/1.1 keep alive header. Disabling keep alive will prevent re-using the same TCP connection to fire multiple requests, recommended when using one request per connection.", - - FLAG flag_jsonrpc_experimental: (bool) = false, or |c: &Config| c.rpc.as_ref()?.experimental_rpcs.clone(), - "--jsonrpc-experimental", - "Enable experimental RPCs. Enable to have access to methods from unfinalised EIPs in all namespaces", - - ARG arg_jsonrpc_port: (u16) = 8545u16, or |c: &Config| c.rpc.as_ref()?.port.clone(), - "--jsonrpc-port=[PORT]", - "Specify the port portion of the HTTP JSON-RPC API server.", - - ARG arg_jsonrpc_interface: (String) = "local", or |c: &Config| c.rpc.as_ref()?.interface.clone(), - "--jsonrpc-interface=[IP]", - "Specify the hostname portion of the HTTP JSON-RPC API server, IP should be an interface's IP address, or all (all interfaces) or local.", - - ARG arg_jsonrpc_apis: (String) = "web3,eth,pubsub,net,parity,private,parity_pubsub,traces,rpc,parity_transactions_pool", or |c: &Config| c.rpc.as_ref()?.apis.as_ref().map(|vec| vec.join(",")), - "--jsonrpc-apis=[APIS]", - "Specify the APIs available through the HTTP JSON-RPC interface using a comma-delimited list of API names. Possible names are: all, safe, debug, web3, net, eth, pubsub, personal, signer, parity, parity_pubsub, parity_accounts, parity_set, traces, rpc, secretstore. You can also disable a specific API by putting '-' in the front, example: all,-personal. 'safe' enables the following APIs: web3, net, eth, pubsub, parity, parity_pubsub, traces, rpc", - - ARG arg_jsonrpc_hosts: (String) = "none", or |c: &Config| c.rpc.as_ref()?.hosts.as_ref().map(|vec| vec.join(",")), - "--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\",.", - - ARG arg_jsonrpc_threads: (Option) = None, or |_| None, - "--jsonrpc-threads=[NUM]", - "DEPRECATED, DOES NOTHING", - - ARG arg_jsonrpc_server_threads: (Option) = Some(4), or |c: &Config| c.rpc.as_ref()?.server_threads, - "--jsonrpc-server-threads=[NUM]", - "Enables multiple threads handling incoming connections for HTTP JSON-RPC server.", - - ARG arg_jsonrpc_cors: (String) = "none", or |c: &Config| c.rpc.as_ref()?.cors.as_ref().map(|vec| vec.join(",")), - "--jsonrpc-cors=[URL]", - "Specify CORS header for HTTP JSON-RPC API responses. Special options: \"all\", \"none\".", - - ARG arg_jsonrpc_max_payload: (Option) = None, or |c: &Config| c.rpc.as_ref()?.max_payload, - "--jsonrpc-max-payload=[MB]", - "Specify maximum size for HTTP JSON-RPC requests in megabytes.", - - ARG arg_poll_lifetime: (u32) = 60u32, or |c: &Config| c.rpc.as_ref()?.poll_lifetime.clone(), - "--poll-lifetime=[S]", - "Set the RPC filter lifetime to S seconds. The filter has to be polled at least every S seconds , otherwise it is removed.", - - ["API and Console Options – WebSockets"] - FLAG flag_no_ws: (bool) = false, or |c: &Config| c.websockets.as_ref()?.disable.clone(), - "--no-ws", - "Disable the WebSockets JSON-RPC server.", - - ARG arg_ws_port: (u16) = 8546u16, or |c: &Config| c.websockets.as_ref()?.port.clone(), - "--ws-port=[PORT]", - "Specify the port portion of the WebSockets JSON-RPC server.", - - ARG arg_ws_interface: (String) = "local", or |c: &Config| c.websockets.as_ref()?.interface.clone(), - "--ws-interface=[IP]", - "Specify the hostname portion of the WebSockets JSON-RPC server, IP should be an interface's IP address, or all (all interfaces) or local.", - - ARG arg_ws_apis: (String) = "web3,eth,pubsub,net,parity,parity_pubsub,private,traces,rpc,parity_transactions_pool", or |c: &Config| c.websockets.as_ref()?.apis.as_ref().map(|vec| vec.join(",")), - "--ws-apis=[APIS]", - "Specify the JSON-RPC APIs available through the WebSockets interface using a comma-delimited list of API names. Possible names are: all, safe, web3, net, eth, pubsub, personal, signer, parity, parity_pubsub, parity_accounts, parity_set, traces, rpc, secretstore. You can also disable a specific API by putting '-' in the front, example: all,-personal. 'safe' enables the following APIs: web3, net, eth, pubsub, parity, parity_pubsub, traces, rpc", - - ARG arg_ws_origins: (String) = "parity://*,chrome-extension://*,moz-extension://*", or |c: &Config| c.websockets.as_ref()?.origins.as_ref().map(|vec| vec.join(",")), - "--ws-origins=[URL]", - "Specify Origin header values allowed to connect. Special options: \"all\", \"none\".", - - ARG arg_ws_hosts: (String) = "none", or |c: &Config| c.websockets.as_ref()?.hosts.as_ref().map(|vec| vec.join(",")), - "--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\".", - - ARG arg_ws_max_connections: (usize) = 100usize, or |c: &Config| c.websockets.as_ref()?.max_connections, - "--ws-max-connections=[CONN]", - "Maximum number of allowed concurrent WebSockets JSON-RPC connections.", - - ["API and Console Options – IPC"] - FLAG flag_no_ipc: (bool) = false, or |c: &Config| c.ipc.as_ref()?.disable.clone(), - "--no-ipc", - "Disable JSON-RPC over IPC service.", - - ARG arg_ipc_path: (String) = if cfg!(windows) { r"\\.\pipe\jsonrpc.ipc" } else { "$BASE/jsonrpc.ipc" }, or |c: &Config| c.ipc.as_ref()?.path.clone(), - "--ipc-path=[PATH]", - "Specify custom path for JSON-RPC over IPC service.", - - ARG arg_ipc_chmod: (String) = "660", or |c: &Config| c.ipc.as_ref()?.chmod.clone(), - "--ipc-chmod=[NUM]", - "Specify octal value for ipc socket permissions (unix/bsd only)", - - ARG arg_ipc_apis: (String) = "web3,eth,pubsub,net,parity,parity_pubsub,parity_accounts,private,traces,rpc,parity_transactions_pool", or |c: &Config| c.ipc.as_ref()?.apis.as_ref().map(|vec| vec.join(",")), - "--ipc-apis=[APIS]", - "Specify custom API set available via JSON-RPC over IPC using a comma-delimited list of API names. Possible names are: all, safe, web3, net, eth, pubsub, personal, signer, parity, parity_pubsub, parity_accounts, parity_set, traces, rpc, secretstore. You can also disable a specific API by putting '-' in the front, example: all,-personal. 'safe' enables the following APIs: web3, net, eth, pubsub, parity, parity_pubsub, traces, rpc", - - ["Light Client Options"] - ARG arg_on_demand_response_time_window: (Option) = None, or |c: &Config| c.light.as_ref()?.on_demand_response_time_window, - "--on-demand-time-window=[S]", - "Specify the maximum time to wait for a successful response", - - ARG arg_on_demand_request_backoff_start: (Option) = None, or |c: &Config| c.light.as_ref()?.on_demand_request_backoff_start, - "--on-demand-start-backoff=[S]", - "Specify light client initial backoff time for a request", - - ARG arg_on_demand_request_backoff_max: (Option) = None, or |c: &Config| c.light.as_ref()?.on_demand_request_backoff_max, - "--on-demand-end-backoff=[S]", - "Specify light client maximum backoff time for a request", - - ARG arg_on_demand_request_backoff_rounds_max: (Option) = None, or |c: &Config| c.light.as_ref()?.on_demand_request_backoff_rounds_max, - "--on-demand-max-backoff-rounds=[TIMES]", - "Specify light client maximum number of backoff iterations for a request", - - ARG arg_on_demand_request_consecutive_failures: (Option) = None, or |c: &Config| c.light.as_ref()?.on_demand_request_consecutive_failures, - "--on-demand-consecutive-failures=[TIMES]", - "Specify light client the number of failures for a request until it gets exponentially backed off", - - ["Secret Store Options"] - FLAG flag_no_secretstore: (bool) = false, or |c: &Config| c.secretstore.as_ref()?.disable.clone(), - "--no-secretstore", - "Disable Secret Store functionality.", - - FLAG flag_no_secretstore_http: (bool) = false, or |c: &Config| c.secretstore.as_ref()?.disable_http.clone(), - "--no-secretstore-http", - "Disable Secret Store HTTP API.", - - FLAG flag_no_secretstore_auto_migrate: (bool) = false, or |c: &Config| c.secretstore.as_ref()?.disable_auto_migrate.clone(), - "--no-secretstore-auto-migrate", - "Do not run servers set change session automatically when servers set changes. This option has no effect when servers set is read from configuration file.", - - ARG arg_secretstore_http_cors: (String) = "none", or |c: &Config| c.secretstore.as_ref()?.cors.as_ref().map(|vec| vec.join(",")), - "--secretstore-http-cors=[URL]", - "Specify CORS header for Secret Store HTTP API responses. Special options: \"all\", \"none\".", - - ARG arg_secretstore_acl_contract: (Option) = Some("registry".into()), or |c: &Config| c.secretstore.as_ref()?.acl_contract.clone(), - "--secretstore-acl-contract=[SOURCE]", - "Secret Store permissioning contract address source: none, registry (contract address is read from 'secretstore_acl_checker' entry in registry) or address.", - - ARG arg_secretstore_contract: (Option) = None, or |c: &Config| c.secretstore.as_ref()?.service_contract.clone(), - "--secretstore-contract=[SOURCE]", - "Secret Store Service contract address source: none, registry (contract address is read from 'secretstore_service' entry in registry) or address.", - - ARG arg_secretstore_srv_gen_contract: (Option) = None, or |c: &Config| c.secretstore.as_ref()?.service_contract_srv_gen.clone(), - "--secretstore-srv-gen-contract=[SOURCE]", - "Secret Store Service server key generation contract address source: none, registry (contract address is read from 'secretstore_service_srv_gen' entry in registry) or address.", - - ARG arg_secretstore_srv_retr_contract: (Option) = None, or |c: &Config| c.secretstore.as_ref()?.service_contract_srv_retr.clone(), - "--secretstore-srv-retr-contract=[SOURCE]", - "Secret Store Service server key retrieval contract address source: none, registry (contract address is read from 'secretstore_service_srv_retr' entry in registry) or address.", - - ARG arg_secretstore_doc_store_contract: (Option) = None, or |c: &Config| c.secretstore.as_ref()?.service_contract_doc_store.clone(), - "--secretstore-doc-store-contract=[SOURCE]", - "Secret Store Service document key store contract address source: none, registry (contract address is read from 'secretstore_service_doc_store' entry in registry) or address.", - - ARG arg_secretstore_doc_sretr_contract: (Option) = None, or |c: &Config| c.secretstore.as_ref()?.service_contract_doc_sretr.clone(), - "--secretstore-doc-sretr-contract=[SOURCE]", - "Secret Store Service document key shadow retrieval contract address source: none, registry (contract address is read from 'secretstore_service_doc_sretr' entry in registry) or address.", - - ARG arg_secretstore_nodes: (String) = "", or |c: &Config| c.secretstore.as_ref()?.nodes.as_ref().map(|vec| vec.join(",")), - "--secretstore-nodes=[NODES]", - "Comma-separated list of other secret store cluster nodes in form NODE_PUBLIC_KEY_IN_HEX@NODE_IP_ADDR:NODE_PORT.", - - ARG arg_secretstore_server_set_contract: (Option) = Some("registry".into()), or |c: &Config| c.secretstore.as_ref()?.server_set_contract.clone(), - "--secretstore-server-set-contract=[SOURCE]", - "Secret Store server set contract address source: none, registry (contract address is read from 'secretstore_server_set' entry in registry) or address.", - - ARG arg_secretstore_interface: (String) = "local", or |c: &Config| c.secretstore.as_ref()?.interface.clone(), - "--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.", - - ARG arg_secretstore_port: (u16) = 8083u16, or |c: &Config| c.secretstore.as_ref()?.port.clone(), - "--secretstore-port=[PORT]", - "Specify the port portion for listening to Secret Store Key Server internal requests.", - - ARG arg_secretstore_http_interface: (String) = "local", or |c: &Config| c.secretstore.as_ref()?.http_interface.clone(), - "--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.", - - ARG arg_secretstore_http_port: (u16) = 8082u16, or |c: &Config| c.secretstore.as_ref()?.http_port.clone(), - "--secretstore-http-port=[PORT]", - "Specify the port portion for listening to Secret Store Key Server HTTP requests.", - - ARG arg_secretstore_path: (String) = "$BASE/secretstore", or |c: &Config| c.secretstore.as_ref()?.path.clone(), - "--secretstore-path=[PATH]", - "Specify directory where Secret Store should save its data.", - - ARG arg_secretstore_secret: (Option) = None, or |c: &Config| c.secretstore.as_ref()?.self_secret.clone(), - "--secretstore-secret=[SECRET]", - "Hex-encoded secret key of this node.", - - ARG arg_secretstore_admin_public: (Option) = None, or |c: &Config| c.secretstore.as_ref()?.admin_public.clone(), - "--secretstore-admin=[PUBLIC]", - "Hex-encoded public key of secret store administrator.", - - ["Sealing/Mining Options"] - FLAG flag_force_sealing: (bool) = false, or |c: &Config| c.mining.as_ref()?.force_sealing.clone(), - "--force-sealing", - "Force the node to author new blocks as if it were always sealing/mining.", - - FLAG flag_reseal_on_uncle: (bool) = false, or |c: &Config| c.mining.as_ref()?.reseal_on_uncle.clone(), - "--reseal-on-uncle", - "Force the node to author new blocks when a new uncle block is imported.", - - FLAG flag_remove_solved: (bool) = false, or |c: &Config| c.mining.as_ref()?.remove_solved.clone(), - "--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.", - - FLAG flag_tx_queue_no_unfamiliar_locals: (bool) = false, or |c: &Config| c.mining.as_ref()?.tx_queue_no_unfamiliar_locals.clone(), - "--tx-queue-no-unfamiliar-locals", - "Local transactions sent through JSON-RPC (HTTP, WebSockets, etc) will be treated as 'external' if the sending account is unknown.", - - FLAG flag_tx_queue_no_early_reject: (bool) = false, or |c: &Config| c.mining.as_ref()?.tx_queue_no_early_reject.clone(), - "--tx-queue-no-early-reject", - "Disables transaction queue optimization to early reject transactions below minimal effective gas price. This allows local transactions to always enter the pool, despite it being full, but requires additional ecrecover on every transaction.", - - FLAG flag_refuse_service_transactions: (bool) = false, or |c: &Config| c.mining.as_ref()?.refuse_service_transactions.clone(), - "--refuse-service-transactions", - "Always refuse service transactions.", - - FLAG flag_infinite_pending_block: (bool) = false, or |c: &Config| c.mining.as_ref()?.infinite_pending_block.clone(), - "--infinite-pending-block", - "Pending block will be created with maximal possible gas limit and will execute all transactions in the queue. Note that such block is invalid and should never be attempted to be mined.", - - FLAG flag_no_persistent_txqueue: (bool) = false, or |c: &Config| c.parity.as_ref()?.no_persistent_txqueue, - "--no-persistent-txqueue", - "Don't save pending local transactions to disk to be restored whenever the node restarts.", - - // For backward compatibility; Stratum should be enabled if the config file - // contains a `[stratum]` section and it is not explicitly disabled (disable = true) - FLAG flag_stratum: (bool) = false, or |c: &Config| Some(c.stratum.as_ref().map(|s| s.disable != Some(true)).unwrap_or(false)), - "--stratum", - "Run Stratum server for miner push notification.", - - ARG arg_reseal_on_txs: (String) = "own", or |c: &Config| c.mining.as_ref()?.reseal_on_txs.clone(), - "--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.", - - ARG arg_reseal_min_period: (u64) = 2000u64, or |c: &Config| c.mining.as_ref()?.reseal_min_period.clone(), - "--reseal-min-period=[MS]", - "Specify the minimum time between reseals from incoming transactions. MS is time measured in milliseconds.", - - ARG arg_reseal_max_period: (u64) = 120000u64, or |c: &Config| c.mining.as_ref()?.reseal_max_period.clone(), - "--reseal-max-period=[MS]", - "Specify the maximum time since last block to enable force-sealing. MS is time measured in milliseconds.", - - ARG arg_work_queue_size: (usize) = 20usize, or |c: &Config| c.mining.as_ref()?.work_queue_size.clone(), - "--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.", - - ARG arg_relay_set: (String) = "cheap", or |c: &Config| c.mining.as_ref()?.relay_set.clone(), - "--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.", - - ARG arg_usd_per_tx: (String) = "0.0001", or |c: &Config| c.mining.as_ref()?.usd_per_tx.clone(), - "--usd-per-tx=[USD]", - "Amount of USD to be paid for a basic transaction. The minimum gas price is set accordingly.", - - ARG arg_usd_per_eth: (String) = "auto", or |c: &Config| c.mining.as_ref()?.usd_per_eth.clone(), - "--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.", - - ARG arg_price_update_period: (String) = "hourly", or |c: &Config| c.mining.as_ref()?.price_update_period.clone(), - "--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..", - - ARG arg_gas_floor_target: (String) = "8000000", or |c: &Config| c.mining.as_ref()?.gas_floor_target.clone(), - "--gas-floor-target=[GAS]", - "Amount of gas per block to target when sealing a new block.", - - ARG arg_gas_cap: (String) = "10000000", or |c: &Config| c.mining.as_ref()?.gas_cap.clone(), - "--gas-cap=[GAS]", - "A cap on how large we will raise the gas limit per block due to transaction volume.", - - ARG arg_tx_queue_mem_limit: (u32) = 4u32, or |c: &Config| c.mining.as_ref()?.tx_queue_mem_limit.clone(), - "--tx-queue-mem-limit=[MB]", - "Maximum amount of memory that can be used by the transaction queue. Setting this parameter to 0 disables limiting.", - - ARG arg_tx_queue_size: (usize) = 8_192usize, or |c: &Config| c.mining.as_ref()?.tx_queue_size.clone(), - "--tx-queue-size=[LIMIT]", - "Maximum amount of transactions in the queue (waiting to be included in next block).", - - ARG arg_tx_queue_per_sender: (Option) = None, or |c: &Config| c.mining.as_ref()?.tx_queue_per_sender.clone(), - "--tx-queue-per-sender=[LIMIT]", - "Maximum number of transactions per sender in the queue. By default it's 1% of the entire queue, but not less than 16.", - - ARG arg_tx_queue_locals: (Option) = None, or |c: &Config| helpers::join_set(c.mining.as_ref()?.tx_queue_locals.as_ref()), - "--tx-queue-locals=[ACCOUNTS]", - "Specify local accounts for which transactions are prioritized in the queue. ACCOUNTS is a comma-delimited list of addresses.", - - ARG arg_tx_queue_strategy: (String) = "gas_price", or |c: &Config| c.mining.as_ref()?.tx_queue_strategy.clone(), - "--tx-queue-strategy=[S]", - "Prioritization strategy used to order transactions in the queue. S may be: gas_price - Prioritize txs with high gas price", - - ARG arg_stratum_interface: (String) = "local", or |c: &Config| c.stratum.as_ref()?.interface.clone(), - "--stratum-interface=[IP]", - "Interface address for Stratum server.", - - ARG arg_stratum_port: (u16) = 8008u16, or |c: &Config| c.stratum.as_ref()?.port.clone(), - "--stratum-port=[PORT]", - "Port for Stratum server to listen on.", - - ARG arg_min_gas_price: (Option) = None, or |c: &Config| c.mining.as_ref()?.min_gas_price.clone(), - "--min-gas-price=[STRING]", - "Minimum amount of Wei per GAS to be paid for a transaction to be accepted for mining. Overrides --usd-per-tx.", - - ARG arg_gas_price_percentile: (usize) = 50usize, or |c: &Config| c.mining.as_ref()?.gas_price_percentile, - "--gas-price-percentile=[PCT]", - "Set PCT percentile gas price value from last 100 blocks as default gas price when sending transactions.", - - ARG arg_author: (Option) = None, or |c: &Config| c.mining.as_ref()?.author.clone(), - "--author=[ADDRESS]", - "Specify the block author (aka \"coinbase\") address for sending block rewards from sealed blocks. NOTE: MINING WILL NOT WORK WITHOUT THIS OPTION.", // Sealing/Mining Option - - ARG arg_engine_signer: (Option) = None, or |c: &Config| c.mining.as_ref()?.engine_signer.clone(), - "--engine-signer=[ADDRESS]", - "Specify the address which should be used to sign consensus messages and issue blocks. Relevant only to non-PoW chains.", - - ARG arg_tx_gas_limit: (Option) = None, or |c: &Config| c.mining.as_ref()?.tx_gas_limit.clone(), - "--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.", - - ARG arg_tx_time_limit: (Option) = None, or |c: &Config| c.mining.as_ref()?.tx_time_limit.clone(), - "--tx-time-limit=[MS]", - "Maximal time for processing single transaction. If enabled senders of transactions offending the limit will get other transactions penalized.", - - ARG arg_extra_data: (Option) = None, or |c: &Config| c.mining.as_ref()?.extra_data.clone(), - "--extra-data=[STRING]", - "Specify a custom extra-data for authored blocks, no more than 32 characters.", - - ARG arg_notify_work: (Option) = None, or |c: &Config| c.mining.as_ref()?.notify_work.as_ref().map(|vec| vec.join(",")), - "--notify-work=[URLS]", - "URLs to which work package notifications are pushed. URLS should be a comma-delimited list of HTTP URLs.", - - ARG arg_stratum_secret: (Option) = None, or |c: &Config| c.stratum.as_ref()?.secret.clone(), - "--stratum-secret=[STRING]", - "Secret for authorizing Stratum server for peers.", - - ARG arg_max_round_blocks_to_import: (usize) = 12usize, or |c: &Config| c.mining.as_ref()?.max_round_blocks_to_import.clone(), - "--max-round-blocks-to-import=[S]", - "Maximal number of blocks to import for each import round.", - - ["Internal Options"] - FLAG flag_can_restart: (bool) = false, or |_| None, - "--can-restart", - "Executable will auto-restart if exiting with 69", - - ["Miscellaneous Options"] - FLAG flag_no_color: (bool) = false, or |c: &Config| c.misc.as_ref()?.color.map(|c| !c).clone(), - "--no-color", - "Don't use terminal color codes in output.", - - FLAG flag_version: (bool) = false, or |_| None, - "-v, --version", - "Show information about version.", - - FLAG flag_no_config: (bool) = false, or |_| None, - "--no-config", - "Don't load a configuration file.", - - ARG arg_logging: (Option) = None, or |c: &Config| c.misc.as_ref()?.logging.clone(), - "-l, --logging=[LOGGING]", - "Specify the general logging level (error, warn, info, debug or trace). It can also be set for a specific module, example: '-l sync=debug,rpc=trace'", - - ARG arg_log_file: (Option) = None, or |c: &Config| c.misc.as_ref()?.log_file.clone(), - "--log-file=[FILENAME]", - "Specify a filename into which logging should be appended.", - - ["Footprint Options"] - FLAG flag_scale_verifiers: (bool) = false, or |c: &Config| c.footprint.as_ref()?.scale_verifiers.clone(), - "--scale-verifiers", - "Automatically scale amount of verifier threads based on workload. Not guaranteed to be faster.", - - ARG arg_tracing: (String) = "auto", or |c: &Config| c.footprint.as_ref()?.tracing.clone(), - "--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).", // footprint option - - ARG arg_pruning: (String) = "auto", or |c: &Config| c.footprint.as_ref()?.pruning.clone(), - "--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.", - - ARG arg_pruning_history: (u64) = 128u64, or |c: &Config| c.footprint.as_ref()?.pruning_history.clone(), - "--pruning-history=[NUM]", - "Set a minimum number of recent states to keep in memory when pruning is active.", - - ARG arg_pruning_memory: (usize) = 64usize, or |c: &Config| c.footprint.as_ref()?.pruning_memory.clone(), - "--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.", - - ARG arg_cache_size_db: (u32) = 128u32, or |c: &Config| c.footprint.as_ref()?.cache_size_db.clone(), - "--cache-size-db=[MB]", - "Override database cache size.", - - ARG arg_cache_size_blocks: (u32) = 8u32, or |c: &Config| c.footprint.as_ref()?.cache_size_blocks.clone(), - "--cache-size-blocks=[MB]", - "Specify the preferred size of the blockchain cache in megabytes.", - - ARG arg_cache_size_queue: (u32) = 40u32, or |c: &Config| c.footprint.as_ref()?.cache_size_queue.clone(), - "--cache-size-queue=[MB]", - "Specify the maximum size of memory to use for block queue.", - - ARG arg_cache_size_state: (u32) = 25u32, or |c: &Config| c.footprint.as_ref()?.cache_size_state.clone(), - "--cache-size-state=[MB]", - "Specify the maximum size of memory to use for the state cache.", - - ARG arg_db_compaction: (String) = "auto", or |c: &Config| c.footprint.as_ref()?.db_compaction.clone(), - "--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.", - - ARG arg_fat_db: (String) = "auto", or |c: &Config| c.footprint.as_ref()?.fat_db.clone(), - "--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.", - - ARG arg_cache_size: (Option) = None, or |c: &Config| c.footprint.as_ref()?.cache_size.clone(), - "--cache-size=[MB]", - "Set total amount of discretionary memory to use for the entire system, overrides other cache and queue options.", - - ARG arg_num_verifiers: (Option) = None, or |c: &Config| c.footprint.as_ref()?.num_verifiers.clone(), - "--num-verifiers=[INT]", - "Amount of verifier threads to use or to begin with, if verifier auto-scaling is enabled.", - - ["Import/export Options"] - FLAG flag_no_seal_check: (bool) = false, or |_| None, - "--no-seal-check", - "Skip block seal check.", - - ["Snapshot Options"] - FLAG flag_no_periodic_snapshot: (bool) = false, or |c: &Config| c.snapshots.as_ref()?.disable_periodic.clone(), - "--no-periodic-snapshot", - "Disable automated snapshots which usually occur once every 5000 blocks.", - - ARG arg_snapshot_threads: (Option) = None, or |c: &Config| c.snapshots.as_ref()?.processing_threads, - "--snapshot-threads=[NUM]", - "Enables multiple threads for snapshots creation.", - - ["Whisper Options"] - FLAG flag_whisper: (bool) = false, or |c: &Config| c.whisper.as_ref()?.enabled, - "--whisper", - "Does nothing. Whisper has been moved to https://github.com/paritytech/whisper", - - ARG arg_whisper_pool_size: (Option) = None, or |c: &Config| c.whisper.as_ref()?.pool_size.clone(), - "--whisper-pool-size=[MB]", - "Does nothing. Whisper has been moved to https://github.com/paritytech/whisper", - - ["Legacy Options"] - // Options that are hidden from config, but are still unique for its functionality. - - FLAG flag_geth: (bool) = false, or |_| None, - "--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.", - - FLAG flag_import_geth_keys: (bool) = false, or |_| None, - "--import-geth-keys", - "Attempt to import keys from Geth client.", - - // Options that either do nothing, or are replaced by other options. - // FLAG Removed in 1.6 or before. - - FLAG flag_warp: (bool) = false, or |_| None, - "--warp", - "Does nothing; warp sync is enabled by default. Use --no-warp to disable.", - - FLAG flag_jsonrpc: (bool) = false, or |_| None, - "-j, --jsonrpc", - "Does nothing; HTTP JSON-RPC is on by default now.", - - FLAG flag_rpc: (bool) = false, or |_| None, - "--rpc", - "Does nothing; HTTP JSON-RPC is on by default now.", - - FLAG flag_jsonrpc_off: (bool) = false, or |_| None, - "--jsonrpc-off", - "Equivalent to --no-jsonrpc.", - - FLAG flag_webapp: (bool) = false, or |_| None, - "-w, --webapp", - "Does nothing; dapps server has been removed.", - - FLAG flag_dapps_off: (bool) = false, or |_| None, - "--dapps-off", - "Equivalent to --no-dapps.", - - FLAG flag_ipcdisable: (bool) = false, or |_| None, - "--ipcdisable", - "Equivalent to --no-ipc.", - - FLAG flag_ipc_off: (bool) = false, or |_| None, - "--ipc-off", - "Equivalent to --no-ipc.", - - FLAG flag_testnet: (bool) = false, or |_| None, - "--testnet", - "Testnet mode. Equivalent to --chain testnet. Overrides the --keys-path option.", - - FLAG flag_nodiscover: (bool) = false, or |_| None, - "--nodiscover", - "Equivalent to --no-discovery.", - - // FLAG Removed in 1.7. - - FLAG flag_dapps_apis_all: (bool) = false, or |_| None, - "--dapps-apis-all", - "Dapps server is merged with HTTP JSON-RPC server. Use --jsonrpc-apis.", - - // FLAG Removed in 1.11. - - FLAG flag_public_node: (bool) = false, or |_| None, - "--public-node", - "Does nothing; Public node is removed from Parity.", - - FLAG flag_force_ui: (bool) = false, or |_| None, - "--force-ui", - "Does nothing; UI is now a separate project.", - - FLAG flag_no_ui: (bool) = false, or |_| None, - "--no-ui", - "Does nothing; UI is now a separate project.", - - FLAG flag_ui_no_validation: (bool) = false, or |_| None, - "--ui-no-validation", - "Does nothing; UI is now a separate project.", - - // FLAG Removed in 2.0. - - FLAG flag_fast_and_loose: (bool) = false, or |_| None, - "--fast-and-loose", - "Does nothing; DB WAL is always activated.", - - FLAG flag_no_dapps: (bool) = false, or |c: &Config| c.dapps.as_ref()?._legacy_disable.clone(), - "--no-dapps", - "Disable the Dapps server (e.g. status page).", - - // ARG Removed in 1.6 or before. - - ARG arg_etherbase: (Option) = None, or |_| None, - "--etherbase=[ADDRESS]", - "Equivalent to --author ADDRESS.", - - ARG arg_extradata: (Option) = None, or |_| None, - "--extradata=[STRING]", - "Equivalent to --extra-data STRING.", - - ARG arg_datadir: (Option) = None, or |_| None, - "--datadir=[PATH]", - "Equivalent to --base-path PATH.", - - ARG arg_networkid: (Option) = None, or |_| None, - "--networkid=[INDEX]", - "Equivalent to --network-id INDEX.", - - ARG arg_peers: (Option) = None, or |_| None, - "--peers=[NUM]", - "Equivalent to --min-peers NUM.", - - ARG arg_nodekey: (Option) = None, or |_| None, - "--nodekey=[KEY]", - "Equivalent to --node-key KEY.", - - ARG arg_rpcaddr: (Option) = None, or |_| None, - "--rpcaddr=[IP]", - "Equivalent to --jsonrpc-interface IP.", - - ARG arg_rpcport: (Option) = None, or |_| None, - "--rpcport=[PORT]", - "Equivalent to --jsonrpc-port PORT.", - - ARG arg_rpcapi: (Option) = None, or |_| None, - "--rpcapi=[APIS]", - "Equivalent to --jsonrpc-apis APIS.", - - ARG arg_rpccorsdomain: (Option) = None, or |_| None, - "--rpccorsdomain=[URL]", - "Equivalent to --jsonrpc-cors URL.", - - ARG arg_ipcapi: (Option) = None, or |_| None, - "--ipcapi=[APIS]", - "Equivalent to --ipc-apis APIS.", - - ARG arg_ipcpath: (Option) = None, or |_| None, - "--ipcpath=[PATH]", - "Equivalent to --ipc-path PATH.", - - ARG arg_gasprice: (Option) = None, or |_| None, - "--gasprice=[WEI]", - "Equivalent to --min-gas-price WEI.", - - ARG arg_cache: (Option) = None, or |_| None, - "--cache=[MB]", - "Equivalent to --cache-size MB.", - - // ARG Removed in 1.7. - - ARG arg_dapps_port: (Option) = None, or |c: &Config| c.dapps.as_ref()?._legacy_port.clone(), - "--dapps-port=[PORT]", - "Does nothing; dapps server has been removed.", - - ARG arg_dapps_interface: (Option) = None, or |c: &Config| c.dapps.as_ref()?._legacy_interface.clone(), - "--dapps-interface=[IP]", - "Does nothing; dapps server has been removed.", - - ARG arg_dapps_hosts: (Option) = None, or |c: &Config| c.dapps.as_ref()?._legacy_hosts.as_ref().map(|vec| vec.join(",")), - "--dapps-hosts=[HOSTS]", - "Does nothing; dapps server has been removed.", - - ARG arg_dapps_cors: (Option) = None, or |c: &Config| c.dapps.as_ref()?._legacy_cors.clone(), - "--dapps-cors=[URL]", - "Does nothing; dapps server has been removed.", - - ARG arg_dapps_user: (Option) = None, or |c: &Config| c.dapps.as_ref()?._legacy_user.clone(), - "--dapps-user=[USERNAME]", - "Dapps server authentication has been removed.", - - ARG arg_dapps_pass: (Option) = None, or |c: &Config| c.dapps.as_ref()?._legacy_pass.clone(), - "--dapps-pass=[PASSWORD]", - "Dapps server authentication has been removed.", - - // ARG removed in 1.11. - - ARG arg_ui_interface: (Option) = None, or |_| None, - "--ui-interface=[IP]", - "Does nothing; UI is now a separate project.", - - ARG arg_ui_hosts: (Option) = None, or |_| None, - "--ui-hosts=[HOSTS]", - "Does nothing; UI is now a separate project.", - - ARG arg_ui_port: (Option) = None, or |_| None, - "--ui-port=[PORT]", - "Does nothing; UI is now a separate project.", - - ARG arg_tx_queue_ban_count: (Option) = None, or |c: &Config| c.mining.as_ref()?.tx_queue_ban_count.clone(), - "--tx-queue-ban-count=[C]", - "Not supported.", - - ARG arg_tx_queue_ban_time: (Option) = None, or |c: &Config| c.mining.as_ref()?.tx_queue_ban_time.clone(), - "--tx-queue-ban-time=[SEC]", - "Not supported.", - - // ARG removed in 2.0. - - ARG arg_dapps_path: (Option) = None, or |c: &Config| c.dapps.as_ref()?._legacy_path.clone(), - "--dapps-path=[PATH]", - "Specify directory where dapps should be installed.", - - ARG arg_ntp_servers: (Option) = None, or |_| None, - "--ntp-servers=[HOSTS]", - "Does nothing; checking if clock is sync with NTP servers is now done on the UI.", - } -} - -#[derive(Default, Debug, PartialEq, Deserialize)] -#[serde(deny_unknown_fields)] -struct Config { - parity: Option, - account: Option, - ui: Option, - network: Option, - rpc: Option, - websockets: Option, - ipc: Option, - dapps: Option, - secretstore: Option, - private_tx: Option, - mining: Option, - footprint: Option, - snapshots: Option, - misc: Option, - stratum: Option, - whisper: Option, - light: Option, -} - -#[derive(Default, Debug, PartialEq, Deserialize)] -#[serde(deny_unknown_fields)] -struct Operating { - mode: Option, - mode_timeout: Option, - mode_alarm: Option, - auto_update: Option, - auto_update_delay: Option, - auto_update_check_frequency: Option, - release_track: Option, - no_download: Option, - no_consensus: Option, - chain: Option, - base_path: Option, - db_path: Option, - keys_path: Option, - identity: Option, - light: Option, - no_persistent_txqueue: Option, - no_hardcoded_sync: Option, - sync_until: Option, - - #[serde(rename = "public_node")] - _legacy_public_node: Option, -} - -#[derive(Default, Debug, PartialEq, Deserialize)] -#[serde(deny_unknown_fields)] -struct Account { - unlock: Option>, - enable_signing_queue: Option, - password: Option>, - keys_iterations: Option, - refresh_time: Option, - fast_unlock: Option, -} - -#[derive(Default, Debug, PartialEq, Deserialize)] -#[serde(deny_unknown_fields)] -struct PrivateTransactions { - enabled: Option, - state_offchain: Option, - signer: Option, - validators: Option>, - account: Option, - passwords: Option, - sstore_url: Option, - sstore_threshold: Option, -} - -#[derive(Default, Debug, PartialEq, Deserialize)] -#[serde(deny_unknown_fields)] -struct Ui { - path: Option, - - #[serde(rename = "force")] - _legacy_force: Option, - #[serde(rename = "disable")] - _legacy_disable: Option, - #[serde(rename = "port")] - _legacy_port: Option, - #[serde(rename = "interface")] - _legacy_interface: Option, - #[serde(rename = "hosts")] - _legacy_hosts: Option>, -} - -#[derive(Default, Debug, PartialEq, Deserialize)] -#[serde(deny_unknown_fields)] -struct Network { - warp: Option, - warp_barrier: Option, - port: Option, - interface: Option, - min_peers: Option, - max_peers: Option, - snapshot_peers: Option, - max_pending_peers: Option, - nat: Option, - allow_ips: Option, - id: Option, - bootnodes: Option>, - discovery: Option, - node_key: Option, - reserved_peers: Option, - reserved_only: Option, - no_serve_light: Option, -} - -#[derive(Default, Debug, PartialEq, Deserialize)] -#[serde(deny_unknown_fields)] -struct Rpc { - disable: Option, - port: Option, - interface: Option, - cors: Option>, - apis: Option>, - hosts: Option>, - server_threads: Option, - max_payload: Option, - keep_alive: Option, - experimental_rpcs: Option, - poll_lifetime: Option, - allow_missing_blocks: Option, -} - -#[derive(Default, Debug, PartialEq, Deserialize)] -#[serde(deny_unknown_fields)] -struct Ws { - disable: Option, - port: Option, - interface: Option, - apis: Option>, - origins: Option>, - hosts: Option>, - max_connections: Option, -} - -#[derive(Default, Debug, PartialEq, Deserialize)] -#[serde(deny_unknown_fields)] -struct Ipc { - chmod: Option, - disable: Option, - path: Option, - apis: Option>, -} - -#[derive(Default, Debug, PartialEq, Deserialize)] -#[serde(deny_unknown_fields)] -struct Dapps { - #[serde(rename = "disable")] - _legacy_disable: Option, - #[serde(rename = "port")] - _legacy_port: Option, - #[serde(rename = "interface")] - _legacy_interface: Option, - #[serde(rename = "hosts")] - _legacy_hosts: Option>, - #[serde(rename = "cors")] - _legacy_cors: Option, - #[serde(rename = "path")] - _legacy_path: Option, - #[serde(rename = "user")] - _legacy_user: Option, - #[serde(rename = "pass")] - _legacy_pass: Option, -} - -#[derive(Default, Debug, PartialEq, Deserialize)] -#[serde(deny_unknown_fields)] -struct SecretStore { - disable: Option, - disable_http: Option, - disable_auto_migrate: Option, - acl_contract: Option, - service_contract: Option, - service_contract_srv_gen: Option, - service_contract_srv_retr: Option, - service_contract_doc_store: Option, - service_contract_doc_sretr: Option, - self_secret: Option, - admin_public: Option, - nodes: Option>, - server_set_contract: Option, - interface: Option, - port: Option, - http_interface: Option, - http_port: Option, - path: Option, - cors: Option> -} - -#[derive(Default, Debug, PartialEq, Deserialize)] -#[serde(deny_unknown_fields)] -struct Mining { - author: Option, - engine_signer: Option, - force_sealing: Option, - reseal_on_uncle: Option, - reseal_on_txs: Option, - reseal_min_period: Option, - reseal_max_period: Option, - work_queue_size: Option, - tx_gas_limit: Option, - tx_time_limit: Option, - relay_set: Option, - min_gas_price: Option, - gas_price_percentile: Option, - usd_per_tx: Option, - usd_per_eth: Option, - price_update_period: Option, - gas_floor_target: Option, - gas_cap: Option, - extra_data: Option, - tx_queue_size: Option, - tx_queue_per_sender: Option, - tx_queue_mem_limit: Option, - tx_queue_locals: Option>, - tx_queue_strategy: Option, - tx_queue_ban_count: Option, - tx_queue_ban_time: Option, - tx_queue_no_unfamiliar_locals: Option, - tx_queue_no_early_reject: Option, - remove_solved: Option, - notify_work: Option>, - refuse_service_transactions: Option, - infinite_pending_block: Option, - max_round_blocks_to_import: Option, -} - -#[derive(Default, Debug, PartialEq, Deserialize)] -#[serde(deny_unknown_fields)] -struct Stratum { - disable: Option, - interface: Option, - port: Option, - secret: Option, -} - -#[derive(Default, Debug, PartialEq, Deserialize)] -#[serde(deny_unknown_fields)] -struct Footprint { - tracing: Option, - pruning: Option, - pruning_history: Option, - pruning_memory: Option, - fast_and_loose: Option, - cache_size: Option, - cache_size_db: Option, - cache_size_blocks: Option, - cache_size_queue: Option, - cache_size_state: Option, - db_compaction: Option, - fat_db: Option, - scale_verifiers: Option, - num_verifiers: Option, -} - -#[derive(Default, Debug, PartialEq, Deserialize)] -#[serde(deny_unknown_fields)] -struct Snapshots { - disable_periodic: Option, - processing_threads: Option, -} - -#[derive(Default, Debug, PartialEq, Deserialize)] -#[serde(deny_unknown_fields)] -struct Misc { - logging: Option, - log_file: Option, - color: Option, - ports_shift: Option, - unsafe_expose: Option, -} - -#[derive(Default, Debug, PartialEq, Deserialize)] -#[serde(deny_unknown_fields)] -struct Whisper { - enabled: Option, - pool_size: Option, -} - -#[derive(Default, Debug, PartialEq, Deserialize)] -#[serde(deny_unknown_fields)] -struct Light { - on_demand_response_time_window: Option, - on_demand_request_backoff_start: Option, - on_demand_request_backoff_max: Option, - on_demand_request_backoff_rounds_max: Option, - on_demand_request_consecutive_failures: Option, -} - -#[cfg(test)] -mod tests { - use super::{ - Args, ArgsError, - Config, Operating, Account, Ui, Network, Ws, Rpc, Ipc, Dapps, Mining, Footprint, - Snapshots, Misc, Whisper, SecretStore, Light, - }; - use toml; - use clap::{ErrorKind as ClapErrorKind}; - - #[test] - fn should_accept_any_argument_order() { - let args = Args::parse(&["parity", "--no-warp", "account", "list"]).unwrap(); - assert_eq!(args.flag_no_warp, true); - - let args = Args::parse(&["parity", "account", "list", "--no-warp"]).unwrap(); - assert_eq!(args.flag_no_warp, true); - - let args = Args::parse(&["parity", "--chain=dev", "account", "list"]).unwrap(); - assert_eq!(args.arg_chain, "dev"); - - let args = Args::parse(&["parity", "account", "list", "--chain=dev"]).unwrap(); - assert_eq!(args.arg_chain, "dev"); - } - - #[test] - fn should_not_crash_on_warp() { - let args = Args::parse(&["parity", "--warp"]); - assert!(args.is_ok()); - - let args = Args::parse(&["parity", "account", "list", "--warp"]); - assert!(args.is_ok()); - } - - #[test] - fn should_reject_invalid_values() { - let args = Args::parse(&["parity", "--cache=20"]); - assert!(args.is_ok()); - - let args = Args::parse(&["parity", "--cache=asd"]); - assert!(args.is_err()); - } - - #[test] - fn should_parse_args_and_flags() { - let args = Args::parse(&["parity", "--no-warp"]).unwrap(); - assert_eq!(args.flag_no_warp, true); - - let args = Args::parse(&["parity", "--pruning", "archive"]).unwrap(); - assert_eq!(args.arg_pruning, "archive"); - - let args = Args::parse(&["parity", "export", "state", "--no-storage"]).unwrap(); - assert_eq!(args.flag_export_state_no_storage, true); - - let args = Args::parse(&["parity", "export", "state", "--min-balance","123"]).unwrap(); - assert_eq!(args.arg_export_state_min_balance, Some("123".to_string())); - } - - #[test] - fn should_exit_gracefully_on_unknown_argument() { - let result = Args::parse(&["parity", "--please-exit-gracefully"]); - assert!( - match result { - Err(ArgsError::Clap(ref clap_error)) if clap_error.kind == ClapErrorKind::UnknownArgument => true, - _ => false - } - ); - } - - #[test] - fn should_use_subcommand_arg_default() { - let args = Args::parse(&["parity", "export", "state", "--at", "123"]).unwrap(); - assert_eq!(args.arg_export_state_at, "123"); - assert_eq!(args.arg_snapshot_at, "latest"); - - let args = Args::parse(&["parity", "snapshot", "--at", "123", "file.dump"]).unwrap(); - assert_eq!(args.arg_snapshot_at, "123"); - assert_eq!(args.arg_export_state_at, "latest"); - - let args = Args::parse(&["parity", "export", "state"]).unwrap(); - assert_eq!(args.arg_snapshot_at, "latest"); - assert_eq!(args.arg_export_state_at, "latest"); - - let args = Args::parse(&["parity", "snapshot", "file.dump"]).unwrap(); - assert_eq!(args.arg_snapshot_at, "latest"); - assert_eq!(args.arg_export_state_at, "latest"); - } - - #[test] - fn should_parse_multiple_values() { - let args = Args::parse(&["parity", "account", "import", "~/1", "~/2"]).unwrap(); - assert_eq!(args.arg_account_import_path, Some(vec!["~/1".to_owned(), "~/2".to_owned()])); - - let args = Args::parse(&["parity", "account", "import", "~/1,ext"]).unwrap(); - assert_eq!(args.arg_account_import_path, Some(vec!["~/1,ext".to_owned()])); - - let args = Args::parse(&["parity", "--secretstore-nodes", "abc@127.0.0.1:3333,cde@10.10.10.10:4444"]).unwrap(); - assert_eq!(args.arg_secretstore_nodes, "abc@127.0.0.1:3333,cde@10.10.10.10:4444"); - - let args = Args::parse(&["parity", "--password", "~/.safe/1", "--password", "~/.safe/2", "--ui-port", "8123"]).unwrap(); - assert_eq!(args.arg_password, vec!["~/.safe/1".to_owned(), "~/.safe/2".to_owned()]); - assert_eq!(args.arg_ui_port, Some(8123)); - - let args = Args::parse(&["parity", "--password", "~/.safe/1,~/.safe/2", "--ui-port", "8123"]).unwrap(); - assert_eq!(args.arg_password, vec!["~/.safe/1".to_owned(), "~/.safe/2".to_owned()]); - assert_eq!(args.arg_ui_port, Some(8123)); - } - - #[test] - fn should_parse_global_args_with_subcommand() { - let args = Args::parse(&["parity", "--chain", "dev", "account", "list"]).unwrap(); - assert_eq!(args.arg_chain, "dev".to_owned()); - } - - #[test] - fn should_parse_args_and_include_config() { - // given - let mut config = Config::default(); - let mut operating = Operating::default(); - operating.chain = Some("mordor".into()); - config.parity = Some(operating); - - // when - let args = Args::parse_with_config(&["parity"], config).unwrap(); - - // then - assert_eq!(args.arg_chain, "mordor".to_owned()); - } - - #[test] - fn should_not_use_config_if_cli_is_provided() { - // given - let mut config = Config::default(); - let mut operating = Operating::default(); - operating.chain = Some("mordor".into()); - config.parity = Some(operating); - - // when - let args = Args::parse_with_config(&["parity", "--chain", "xyz"], config).unwrap(); - - // then - assert_eq!(args.arg_chain, "xyz".to_owned()); - } - - #[test] - fn should_use_config_if_cli_is_missing() { - let mut config = Config::default(); - let mut footprint = Footprint::default(); - footprint.pruning_history = Some(128); - config.footprint = Some(footprint); - - // when - let args = Args::parse_with_config(&["parity"], config).unwrap(); - - // then - assert_eq!(args.arg_pruning_history, 128); - } - - #[test] - fn should_disable_stratum() { - // given - let config = toml::from_str(include_str!("./tests/config.stratum_disabled.toml")).unwrap(); - - // when - let args = Args::parse_with_config(&["parity"], config).unwrap(); - - // then - assert_eq!(args.flag_stratum, false); - assert_eq!(args.arg_stratum_interface, "local".to_owned()); - assert_eq!(args.arg_stratum_port, 8008u16); - assert_eq!(args.arg_stratum_secret, None); - } - - #[test] - fn should_disable_stratum_when_missing_section() { - // given - let config = toml::from_str(include_str!("./tests/config.stratum_missing_section.toml")).unwrap(); - - // when - let args = Args::parse_with_config(&["parity"], config).unwrap(); - - // then - assert_eq!(args.flag_stratum, false); - assert_eq!(args.arg_stratum_interface, "local".to_owned()); - assert_eq!(args.arg_stratum_port, 8008u16); - assert_eq!(args.arg_stratum_secret, None); - } - - #[test] - fn should_enable_stratum() { - // given - let config = toml::from_str(include_str!("./tests/config.stratum_enabled.toml")).unwrap(); - - // when - let args = Args::parse_with_config(&["parity"], config).unwrap(); - - // then (with custom configurations) - assert_eq!(args.flag_stratum, true); - assert_eq!(args.arg_stratum_interface, "some_interface".to_owned()); - assert_eq!(args.arg_stratum_port, 8007u16); - assert_eq!(args.arg_stratum_secret, Some("Yellow".to_owned())); - } - - #[test] - fn should_enable_stratum_by_param() { - // given - let config = toml::from_str(include_str!("./tests/config.full.toml")).unwrap(); - - // when - let args = Args::parse_with_config(&["parity", "--stratum"], config).unwrap(); - - // then - assert_eq!(args.flag_stratum, true); - assert_eq!(args.arg_stratum_interface, "local".to_owned()); - assert_eq!(args.arg_stratum_port, 8008u16); - assert_eq!(args.arg_stratum_secret, None); - } - - #[test] - // For backward compatibility; Stratum should be enabled if the config file - // contains a `[stratum]` section and it is not explicitly disabled (disable = true) - fn should_enable_stratum_when_missing_field() { - // given - let config = toml::from_str(include_str!("./tests/config.stratum_missing_field.toml")).unwrap(); - - // when - let args = Args::parse_with_config(&["parity"], config).unwrap(); - - // then - assert_eq!(args.flag_stratum, true); - assert_eq!(args.arg_stratum_interface, "local".to_owned()); - assert_eq!(args.arg_stratum_port, 8008u16); - assert_eq!(args.arg_stratum_secret, None); - } - - #[test] - fn should_parse_full_config() { - // given - let config = toml::from_str(include_str!("./tests/config.full.toml")).unwrap(); - - // when - let args = Args::parse_with_config(&["parity", "--chain", "xyz"], config).unwrap(); - - // then - assert_eq!(args, Args { - // Commands - cmd_dapp: false, - cmd_daemon: false, - cmd_account: false, - cmd_account_new: false, - cmd_account_list: false, - cmd_account_import: false, - cmd_wallet: false, - cmd_wallet_import: false, - cmd_import: false, - cmd_export: false, - cmd_export_blocks: false, - cmd_export_state: false, - cmd_signer: false, - cmd_signer_list: false, - cmd_signer_sign: false, - cmd_signer_reject: false, - cmd_signer_new_token: false, - cmd_snapshot: false, - cmd_restore: false, - cmd_tools: false, - cmd_tools_hash: false, - cmd_db: false, - cmd_db_kill: false, - cmd_db_reset: false, - cmd_export_hardcoded_sync: false, - - // Arguments - arg_daemon_pid_file: None, - arg_import_file: None, - arg_import_format: None, - arg_export_blocks_file: None, - arg_export_blocks_format: None, - arg_export_state_file: None, - arg_export_state_format: None, - arg_snapshot_file: None, - arg_restore_file: None, - arg_tools_hash_file: None, - - arg_enable_signing_queue: false, - arg_signer_sign_id: None, - arg_signer_reject_id: None, - arg_dapp_path: None, - arg_account_import_path: None, - arg_wallet_import_path: None, - arg_db_reset_num: 10, - - // -- Operating Options - arg_mode: "last".into(), - arg_mode_timeout: 300u64, - arg_mode_alarm: 3600u64, - arg_auto_update: "none".into(), - arg_auto_update_delay: 200u16, - arg_auto_update_check_frequency: 50u16, - arg_release_track: "current".into(), - flag_public_node: false, - flag_no_download: false, - flag_no_consensus: false, - arg_chain: "xyz".into(), - arg_base_path: Some("$HOME/.parity".into()), - arg_db_path: Some("$HOME/.parity/chains".into()), - arg_keys_path: "$HOME/.parity/keys".into(), - arg_identity: "".into(), - flag_light: false, - flag_no_hardcoded_sync: false, - flag_no_persistent_txqueue: false, - flag_force_direct: false, - arg_sync_until: None, - - // -- Convenience Options - arg_config: "$BASE/config.toml".into(), - arg_ports_shift: 0, - flag_unsafe_expose: false, - - // -- Account Options - arg_unlock: Some("0xdeadbeefcafe0000000000000000000000000000".into()), - arg_password: vec!["~/.safe/password.file".into()], - arg_keys_iterations: 10240u32, - arg_accounts_refresh: 5u64, - flag_fast_unlock: false, - - // -- Private Transactions Options - flag_private_enabled: true, - flag_private_state_offchain: false, - arg_private_signer: Some("0xdeadbeefcafe0000000000000000000000000000".into()), - arg_private_validators: Some("0xdeadbeefcafe0000000000000000000000000000".into()), - arg_private_passwords: Some("~/.safe/password.file".into()), - arg_private_account: Some("0xdeadbeefcafe0000000000000000000000000000".into()), - arg_private_sstore_url: Some("http://localhost:8082".into()), - arg_private_sstore_threshold: Some(0), - - flag_force_ui: false, - flag_no_ui: false, - arg_ui_port: None, - arg_ui_interface: None, - arg_ui_hosts: None, - arg_ui_path: "$HOME/.parity/signer".into(), - flag_ui_no_validation: false, - - // -- Networking Options - flag_no_warp: false, - arg_port: 30303u16, - arg_interface: "all".into(), - arg_min_peers: Some(25u16), - arg_max_peers: Some(50u16), - arg_max_pending_peers: 64u16, - arg_snapshot_peers: 0u16, - arg_allow_ips: "all".into(), - arg_nat: "any".into(), - arg_network_id: Some(1), - arg_bootnodes: Some("".into()), - flag_no_discovery: false, - arg_node_key: None, - arg_reserved_peers: Some("./path_to_file".into()), - flag_reserved_only: false, - flag_no_ancient_blocks: false, - flag_no_serve_light: false, - - // -- API and Console Options - // RPC - flag_no_jsonrpc: false, - flag_jsonrpc_no_keep_alive: false, - flag_jsonrpc_experimental: false, - arg_jsonrpc_port: 8545u16, - arg_jsonrpc_interface: "local".into(), - arg_jsonrpc_cors: "null".into(), - arg_jsonrpc_apis: "web3,eth,net,parity,traces,rpc,secretstore".into(), - arg_jsonrpc_hosts: "none".into(), - arg_jsonrpc_server_threads: Some(4), - arg_jsonrpc_threads: None, // DEPRECATED, does nothing - arg_jsonrpc_max_payload: None, - arg_poll_lifetime: 60u32, - flag_jsonrpc_allow_missing_blocks: false, - - // WS - flag_no_ws: false, - arg_ws_port: 8546u16, - arg_ws_interface: "local".into(), - arg_ws_apis: "web3,eth,net,parity,traces,rpc,secretstore".into(), - arg_ws_origins: "none".into(), - arg_ws_hosts: "none".into(), - arg_ws_max_connections: 100, - - // IPC - flag_no_ipc: false, - arg_ipc_path: "$HOME/.parity/jsonrpc.ipc".into(), - arg_ipc_apis: "web3,eth,net,parity,parity_accounts,personal,traces,rpc,secretstore".into(), - arg_ipc_chmod: "660".into(), - // DAPPS - arg_dapps_path: Some("$HOME/.parity/dapps".into()), - flag_no_dapps: false, - - // SECRETSTORE - flag_no_secretstore: false, - flag_no_secretstore_http: false, - flag_no_secretstore_auto_migrate: false, - arg_secretstore_acl_contract: Some("registry".into()), - arg_secretstore_contract: Some("none".into()), - arg_secretstore_srv_gen_contract: Some("none".into()), - arg_secretstore_srv_retr_contract: Some("none".into()), - arg_secretstore_doc_store_contract: Some("none".into()), - arg_secretstore_doc_sretr_contract: Some("none".into()), - arg_secretstore_secret: None, - arg_secretstore_admin_public: None, - arg_secretstore_nodes: "".into(), - arg_secretstore_server_set_contract: Some("registry".into()), - arg_secretstore_interface: "local".into(), - arg_secretstore_port: 8083u16, - arg_secretstore_http_interface: "local".into(), - arg_secretstore_http_port: 8082u16, - arg_secretstore_path: "$HOME/.parity/secretstore".into(), - arg_secretstore_http_cors: "null".into(), - - // -- Sealing/Mining Options - arg_author: Some("0xdeadbeefcafe0000000000000000000000000001".into()), - arg_engine_signer: Some("0xdeadbeefcafe0000000000000000000000000001".into()), - flag_force_sealing: true, - arg_reseal_on_txs: "all".into(), - arg_reseal_min_period: 4000u64, - arg_reseal_max_period: 60000u64, - flag_reseal_on_uncle: false, - arg_work_queue_size: 20usize, - arg_tx_gas_limit: Some("10000000".into()), - arg_tx_time_limit: Some(100u64), - arg_relay_set: "cheap".into(), - arg_min_gas_price: Some(0u64), - arg_usd_per_tx: "0.0001".into(), - arg_gas_price_percentile: 50usize, - arg_usd_per_eth: "auto".into(), - arg_price_update_period: "hourly".into(), - arg_gas_floor_target: "8000000".into(), - arg_gas_cap: "10000000".into(), - arg_extra_data: Some("Parity".into()), - flag_tx_queue_no_unfamiliar_locals: false, - flag_tx_queue_no_early_reject: false, - arg_tx_queue_size: 8192usize, - arg_tx_queue_per_sender: None, - arg_tx_queue_mem_limit: 4u32, - arg_tx_queue_locals: Some("0xdeadbeefcafe0000000000000000000000000000".into()), - arg_tx_queue_strategy: "gas_factor".into(), - arg_tx_queue_ban_count: Some(1u16), - arg_tx_queue_ban_time: Some(180u16), - flag_remove_solved: false, - arg_notify_work: Some("http://localhost:3001".into()), - flag_refuse_service_transactions: false, - flag_infinite_pending_block: false, - arg_max_round_blocks_to_import: 12usize, - - flag_stratum: false, - arg_stratum_interface: "local".to_owned(), - arg_stratum_port: 8008u16, - arg_stratum_secret: None, - - // -- Footprint Options - arg_tracing: "auto".into(), - arg_pruning: "auto".into(), - arg_pruning_history: 64u64, - arg_pruning_memory: 500usize, - arg_cache_size_db: 64u32, - arg_cache_size_blocks: 8u32, - arg_cache_size_queue: 50u32, - arg_cache_size_state: 25u32, - arg_cache_size: Some(128), - flag_fast_and_loose: false, - arg_db_compaction: "ssd".into(), - arg_fat_db: "auto".into(), - flag_scale_verifiers: true, - arg_num_verifiers: Some(6), - - // -- Import/Export Options - arg_export_blocks_from: "1".into(), - arg_export_blocks_to: "latest".into(), - flag_no_seal_check: false, - flag_export_state_no_code: false, - flag_export_state_no_storage: false, - arg_export_state_min_balance: None, - arg_export_state_max_balance: None, - - // -- Snapshot Optons - arg_export_state_at: "latest".into(), - arg_snapshot_at: "latest".into(), - flag_no_periodic_snapshot: false, - arg_snapshot_threads: None, - - // -- Light options. - arg_on_demand_response_time_window: Some(2), - arg_on_demand_request_backoff_start: Some(9), - arg_on_demand_request_backoff_max: Some(15), - arg_on_demand_request_backoff_rounds_max: Some(100), - arg_on_demand_request_consecutive_failures: Some(1), - - // -- Whisper options. - flag_whisper: false, - arg_whisper_pool_size: Some(20), - - // -- Legacy Options - flag_warp: false, - flag_geth: false, - flag_testnet: false, - flag_import_geth_keys: false, - arg_warp_barrier: None, - arg_datadir: None, - arg_networkid: None, - arg_peers: None, - arg_nodekey: None, - flag_nodiscover: false, - flag_jsonrpc: false, - flag_jsonrpc_off: false, - flag_webapp: false, - flag_dapps_off: false, - flag_rpc: false, - arg_rpcaddr: None, - arg_rpcport: None, - arg_rpcapi: None, - arg_rpccorsdomain: None, - flag_ipcdisable: false, - flag_ipc_off: false, - arg_ipcapi: None, - arg_ipcpath: None, - arg_gasprice: None, - arg_etherbase: None, - arg_extradata: None, - arg_cache: None, - // Legacy-Dapps - arg_dapps_port: Some(8080), - arg_dapps_interface: Some("local".into()), - arg_dapps_hosts: Some("none".into()), - arg_dapps_cors: None, - arg_dapps_user: Some("test_user".into()), - arg_dapps_pass: Some("test_pass".into()), - flag_dapps_apis_all: false, - - // -- Internal Options - flag_can_restart: false, - - // -- Miscellaneous Options - arg_ntp_servers: None, - flag_version: false, - arg_logging: Some("own_tx=trace".into()), - arg_log_file: Some("/var/log/parity.log".into()), - flag_no_color: false, - flag_no_config: false, - }); - } - - #[test] - fn should_parse_config_and_return_errors() { - let config1 = Args::parse_config(include_str!("./tests/config.invalid1.toml")); - let config2 = Args::parse_config(include_str!("./tests/config.invalid2.toml")); - let config3 = Args::parse_config(include_str!("./tests/config.invalid3.toml")); - let config4 = Args::parse_config(include_str!("./tests/config.invalid4.toml")); - - match (config1, config2, config3, config4) { - ( - Err(ArgsError::Decode(_)), - Err(ArgsError::Decode(_)), - Err(ArgsError::Decode(_)), - Err(ArgsError::Decode(_)), - ) => {}, - (a, b, c, d) => { - assert!(false, "Got invalid error types: {:?}, {:?}, {:?}, {:?}", a, b, c, d); - } - } - } - - #[test] - fn should_deserialize_toml_file() { - let config: Config = toml::from_str(include_str!("./tests/config.toml")).unwrap(); - - assert_eq!(config, Config { - parity: Some(Operating { - mode: Some("dark".into()), - mode_timeout: Some(15u64), - mode_alarm: Some(10u64), - auto_update: None, - auto_update_delay: None, - auto_update_check_frequency: None, - release_track: None, - no_download: None, - no_consensus: None, - chain: Some("./chain.json".into()), - base_path: None, - db_path: None, - keys_path: None, - identity: None, - light: None, - no_hardcoded_sync: None, - no_persistent_txqueue: None, - sync_until: Some(123), - _legacy_public_node: None, - }), - account: Some(Account { - enable_signing_queue: None, - unlock: Some(vec!["0x1".into(), "0x2".into(), "0x3".into()]), - password: Some(vec!["passwdfile path".into()]), - keys_iterations: None, - refresh_time: None, - fast_unlock: None, - }), - ui: Some(Ui { - path: None, - _legacy_force: None, - _legacy_disable: Some(true), - _legacy_port: None, - _legacy_interface: None, - _legacy_hosts: None, - }), - network: Some(Network { - warp: Some(false), - warp_barrier: None, - port: None, - interface: None, - min_peers: Some(10), - max_peers: Some(20), - max_pending_peers: Some(30), - snapshot_peers: Some(40), - allow_ips: Some("public".into()), - nat: Some("any".into()), - id: None, - bootnodes: None, - discovery: Some(true), - node_key: None, - reserved_peers: Some("./path/to/reserved_peers".into()), - reserved_only: Some(true), - no_serve_light: None, - }), - websockets: Some(Ws { - disable: Some(true), - port: None, - interface: None, - apis: None, - origins: Some(vec!["none".into()]), - hosts: None, - max_connections: None, - }), - rpc: Some(Rpc { - disable: Some(true), - port: Some(8180), - interface: None, - cors: None, - apis: None, - hosts: None, - server_threads: Some(13), - max_payload: None, - keep_alive: None, - experimental_rpcs: None, - poll_lifetime: None, - allow_missing_blocks: None - }), - ipc: Some(Ipc { - disable: None, - path: None, - chmod: None, - apis: Some(vec!["rpc".into(), "eth".into()]), - }), - dapps: Some(Dapps { - _legacy_disable: None, - _legacy_port: Some(8080), - _legacy_path: None, - _legacy_interface: None, - _legacy_hosts: None, - _legacy_cors: None, - _legacy_user: Some("username".into()), - _legacy_pass: Some("password".into()) - }), - secretstore: Some(SecretStore { - disable: None, - disable_http: None, - disable_auto_migrate: None, - acl_contract: None, - service_contract: None, - service_contract_srv_gen: None, - service_contract_srv_retr: None, - service_contract_doc_store: None, - service_contract_doc_sretr: None, - self_secret: None, - admin_public: None, - nodes: None, - server_set_contract: None, - interface: None, - port: Some(8083), - http_interface: None, - http_port: Some(8082), - path: None, - cors: None, - }), - private_tx: None, - mining: Some(Mining { - author: Some("0xdeadbeefcafe0000000000000000000000000001".into()), - engine_signer: Some("0xdeadbeefcafe0000000000000000000000000001".into()), - force_sealing: Some(true), - reseal_on_txs: Some("all".into()), - reseal_on_uncle: None, - reseal_min_period: Some(4000), - reseal_max_period: Some(60000), - work_queue_size: None, - relay_set: None, - min_gas_price: None, - gas_price_percentile: None, - usd_per_tx: None, - usd_per_eth: None, - price_update_period: Some("hourly".into()), - gas_floor_target: None, - gas_cap: None, - tx_queue_size: Some(8192), - tx_queue_per_sender: None, - tx_queue_mem_limit: None, - tx_queue_locals: None, - tx_queue_strategy: None, - tx_queue_ban_count: None, - tx_queue_ban_time: None, - tx_queue_no_unfamiliar_locals: None, - tx_queue_no_early_reject: None, - tx_gas_limit: None, - tx_time_limit: None, - extra_data: None, - remove_solved: None, - notify_work: None, - refuse_service_transactions: None, - infinite_pending_block: None, - max_round_blocks_to_import: None, - }), - footprint: Some(Footprint { - tracing: Some("on".into()), - pruning: Some("fast".into()), - pruning_history: Some(64), - pruning_memory: None, - fast_and_loose: None, - cache_size: None, - cache_size_db: Some(256), - cache_size_blocks: Some(16), - cache_size_queue: Some(100), - cache_size_state: Some(25), - db_compaction: Some("ssd".into()), - fat_db: Some("off".into()), - scale_verifiers: Some(false), - num_verifiers: None, - }), - light: Some(Light { - on_demand_response_time_window: Some(2), - on_demand_request_backoff_start: Some(9), - on_demand_request_backoff_max: Some(15), - on_demand_request_backoff_rounds_max: Some(10), - on_demand_request_consecutive_failures: Some(1), - }), - snapshots: Some(Snapshots { - disable_periodic: Some(true), - processing_threads: None, - }), - misc: Some(Misc { - logging: Some("own_tx=trace".into()), - log_file: Some("/var/log/parity.log".into()), - color: Some(true), - ports_shift: Some(0), - unsafe_expose: Some(false), - }), - whisper: Some(Whisper { - enabled: Some(true), - pool_size: Some(50), - }), - stratum: None, - }); - } - - #[test] - fn should_not_accept_min_peers_bigger_than_max_peers() { - match Args::parse(&["parity", "--max-peers=39", "--min-peers=40"]) { - Err(ArgsError::PeerConfiguration) => (), - _ => assert_eq!(false, true), - } - } - - #[test] - fn should_accept_max_peers_equal_or_bigger_than_min_peers() { - Args::parse(&["parity", "--max-peers=40", "--min-peers=40"]).unwrap(); - Args::parse(&["parity", "--max-peers=100", "--min-peers=40"]).unwrap(); - } -} +pub mod args; +pub mod globals; +pub mod parse_cli; +pub mod subcommands; +pub mod config; +pub mod tests; diff --git a/parity/cli/parse_cli.rs b/parity/cli/parse_cli.rs new file mode 100644 index 00000000000..182b45c19ea --- /dev/null +++ b/parity/cli/parse_cli.rs @@ -0,0 +1,12 @@ +use structopt::StructOpt; + +use cli::globals::Globals; +use cli::subcommands::SubCommands; + +#[derive(StructOpt, Debug, Clone, Default)] +pub struct ArgsInput { + #[structopt(subcommand)] + pub subcommands: Option, + #[structopt(flatten)] + pub globals: Globals, +} diff --git a/parity/cli/presets/config.dev-insecure.toml b/parity/cli/presets/config.dev-insecure.toml deleted file mode 100644 index 087db0a1c3f..00000000000 --- a/parity/cli/presets/config.dev-insecure.toml +++ /dev/null @@ -1,12 +0,0 @@ -[parity] -no_consensus = true -chain = "dev" - -[mining] -reseal_min_period = 0 -min_gas_price = 0 - -[rpc] -interface = "all" -apis = ["all"] -hosts = ["all"] diff --git a/parity/cli/presets/config.dev.toml b/parity/cli/presets/config.dev.toml deleted file mode 100644 index 4fc0874c51c..00000000000 --- a/parity/cli/presets/config.dev.toml +++ /dev/null @@ -1,6 +0,0 @@ -[parity] -chain = "dev" - -[mining] -reseal_min_period = 0 -min_gas_price = 0 diff --git a/parity/cli/presets/config.insecure.toml b/parity/cli/presets/config.insecure.toml deleted file mode 100644 index c5ce3845a32..00000000000 --- a/parity/cli/presets/config.insecure.toml +++ /dev/null @@ -1,7 +0,0 @@ -[parity] -no_consensus = true - -[rpc] -interface = "all" -apis = ["all"] -hosts = ["all"] diff --git a/parity/cli/presets/config.mining.toml b/parity/cli/presets/config.mining.toml deleted file mode 100644 index 6d22a0f0878..00000000000 --- a/parity/cli/presets/config.mining.toml +++ /dev/null @@ -1,32 +0,0 @@ -[network] -# Parity will try to maintain connection to at least 50 peers. -min_peers = 50 -# Parity will maintain at most 100 peers. -max_peers = 100 - -[ipc] -# You won't be able to use IPC to interact with Parity. -disable = true - -[dapps] -# You won't be able to access any web Dapps. -disable = true - -[mining] -# Prepare a block to seal even when there are no miners connected. -force_sealing = true -# New pending block will be created for all transactions (both local and external). -reseal_on_txs = "all" -# New pending block will be created only once per 4000 milliseconds. -reseal_min_period = 4000 -# Parity will keep/relay at most 8192 transactions in queue. -tx_queue_size = 8192 -tx_queue_per_sender = 128 - -[footprint] -# If defined will never use more then 1024MB for all caches. (Overrides other cache settings). -cache_size = 1024 - -[misc] -# Logging pattern (`=`, e.g. `own_tx=trace`). -logging = "miner=trace,own_tx=trace" diff --git a/parity/cli/presets/config.non-standard-ports.toml b/parity/cli/presets/config.non-standard-ports.toml deleted file mode 100644 index 5c522d86795..00000000000 --- a/parity/cli/presets/config.non-standard-ports.toml +++ /dev/null @@ -1,7 +0,0 @@ -[network] -# Parity will listen for connections on port 30305. -port = 30305 - -[rpc] -# JSON-RPC over HTTP will be accessible on port 8645. -port = 8645 diff --git a/parity/cli/presets/mod.rs b/parity/cli/presets/mod.rs deleted file mode 100644 index 0ac4ef0f1f7..00000000000 --- a/parity/cli/presets/mod.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of Open Ethereum. - -// Open Ethereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Open Ethereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Open Ethereum. If not, see . - -use std::io::{Error, ErrorKind}; - -pub fn preset_config_string(arg: &str) -> Result<&'static str, Error> { - match arg.to_lowercase().as_ref() { - "dev" => Ok(include_str!("./config.dev.toml")), - "mining" => Ok(include_str!("./config.mining.toml")), - "non-standard-ports" => Ok(include_str!("./config.non-standard-ports.toml")), - "insecure" => Ok(include_str!("./config.insecure.toml")), - "dev-insecure" => Ok(include_str!("./config.dev-insecure.toml")), - _ => Err(Error::new(ErrorKind::InvalidInput, "Config doesn't match any presets [dev, mining, non-standard-ports, insecure, dev-insecure]")) - } -} diff --git a/parity/cli/subcommands.rs b/parity/cli/subcommands.rs new file mode 100644 index 00000000000..ea0322be1cf --- /dev/null +++ b/parity/cli/subcommands.rs @@ -0,0 +1,223 @@ +use serde_derive::Deserialize; +use structopt::StructOpt; + +#[derive(StructOpt, Deserialize, Debug, Clone)] +pub enum SubCommands { + Daemon(Daemon), + Wallet { + #[structopt(subcommand)] + wallet: Wallet, + }, + Account { + #[structopt(subcommand)] + account: Account, + }, + Import(Import), + Export { + #[structopt(subcommand)] + export: Export, + }, + Signer(Signer), + Snapshots(Snapshots), + Restore(Restore), + Db(Db), + #[structopt( + about = "Print the hashed light clients headers of the given --chain (default: mainnet) in a JSON format. To be used as hardcoded headers in a genesis file." + )] + ExportHardcodedSync, +} + +#[derive(StructOpt, Deserialize, Debug, Clone)] +#[structopt(about = "Use parity as a daemon")] +pub struct Daemon { + #[structopt(long = "pid-file", name = "PID-FILE", help = "Path to the pid file")] + pub pid_file: Option, +} + +#[derive(StructOpt, Deserialize, Debug, Clone)] +#[structopt(about = "Manage accounts")] +pub enum Account { + #[structopt( + about = "Create a new account (and its associated key) for the given --chain [default: mainnet]" + )] + New, + #[structopt(about = "List existing accounts of the given --chain [default: mainnet]")] + List, + #[structopt( + about = "Import accounts from JSON UTC keystore files to the specified --chain [default: mainnet]" + )] + // FIXME: The original parser implementation had this as `Option>` but this is not + // supported by structopt yet, referring to issue + // [#364](https://github.com/TeXitoi/structopt/issues/364) + Import { path: Vec }, +} + +#[derive(StructOpt, Deserialize, Debug, Clone)] +#[structopt(about = "Manage wallet")] +pub enum Wallet { + #[structopt(help = "Import wallet into the given chain (default: mainnet)")] + Import { + #[structopt(name = "PATH", help = "Path to the wallet")] + path: Option, + }, +} + +#[derive(StructOpt, Deserialize, Debug, Clone)] +#[structopt( + about = "Import blockchain data from a file to the given chain database (default: mainnet)" +)] +pub struct Import { + #[structopt( + long, + name = "FORMAT", + help = "Import in a given format, FORMAT must be either 'hex' or 'binary'. (default: auto)" + )] + pub format: Option, + + #[structopt(name = "FILE", long, help = "Path to the file to import from")] + pub file: Option, +} + +#[derive(StructOpt, Deserialize, Debug, Clone)] +#[structopt(about = "Export blockchain")] +pub enum Export { + Blocks(ExportBlocks), + State(ExportState), +} + +#[derive(StructOpt, Deserialize, Debug, Clone)] +#[structopt( + about = "Export the blockchain blocks from the given chain database [default: mainnet] into a file. The command requires the chain to be synced with --fat-db on." +)] +pub struct ExportBlocks { + #[structopt( + long, + name = "FORMAT", + help = "Export in a given format. FORMAT must be 'hex' or 'binary'. [default: binary]" + )] + pub format: Option, + + #[structopt( + long, + name = "FROM_BLOCK", + help = "Export from block FROM_BLOCK, which may be an index or hash ", + default_value = "1" + )] + pub from: String, + + #[structopt( + long, + name = "TO_BLOCK", + help = "Export to (including TO_BLOCK) block TO_BLOCK, which may be an index, hash or 'latest'", + default_value = "latest" + )] + pub to: String, + #[structopt(help = "Path to the exported file", name = "FILE")] + pub file: Option, +} + +#[derive(StructOpt, Deserialize, Debug, Clone)] +#[structopt( + about = "Export the blockchain state from the given chain [default: mainnet] into a file. The command requires the chain to be synced with --fat-db on." +)] +pub struct ExportState { + #[structopt(long = "no-storage", help = "Don't export account storage.")] + pub no_storage: bool, + + #[structopt(long = "no-code", help = "Don't export account code.")] + pub no_code: bool, + + #[structopt( + long = "max-balance", + name = "MAX_WEI", + help = "Don't export accounts with balance greater than specified." + )] + pub max_balance: Option, + + #[structopt( + long = "min-balance", + name = "MIN_WEI", + help = "Don't export accounts with balance less than specified." + )] + pub min_balance: Option, + + #[structopt( + default_value = "latest", + long, + name = "BLOCK", + help = "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" + )] + pub at: String, + + #[structopt( + long, + name = "FORMAT", + help = "Export in a given format. FORMAT must be either 'hex' or 'binary'. [default: binary]" + )] + pub format: Option, + + #[structopt(long = "file", name = "FILE", help = "Path to the exported file")] + pub file: Option, +} + +#[derive(StructOpt, Deserialize, Debug, Clone)] +#[structopt(about = "Manage Signer")] +pub enum Signer { + #[structopt( + about = "Generate a new signer-authentication token for the given --chain (default: mainnet)" + )] + NewToken, + #[structopt( + about = "List the signer-authentication tokens from given --chain (default: mainnet)" + )] + List, + #[structopt(about = "Sign")] + Sign { + #[structopt(name = "ID")] + id: Option, + }, + #[structopt(about = "Reject")] + Reject { + #[structopt(name = "ID")] + id: Option, + }, +} + +#[derive(StructOpt, Deserialize, Debug, Clone)] +#[structopt(about = "Make a snapshot of the database of the given chain (default: mainnet)")] +pub struct Snapshots { + #[structopt( + default_value = "latest", + name = "BLOCK", + help = "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" + )] + pub at: String, + + #[structopt(name = "FILE", help = "Path to the file to export to")] + pub file: Option, +} + +#[derive(StructOpt, Deserialize, Debug, Clone)] +#[structopt( + about = "Restore the databse of the given chain (default: mainnet) from a snapshot file" +)] +pub struct Restore { + #[structopt(name = "FILE", help = "Path to the file to restore from")] + pub file: Option, +} + +#[derive(StructOpt, Deserialize, Debug, Clone)] +#[structopt(about = "Manage the Database representing the state of the blockchain on this system")] +pub enum Db { + #[structopt(about = "Clean the database of the given --chain (default: mainnet)")] + Kill, + #[structopt(about = "Removes NUM latests blocks from the db")] + Reset { + #[structopt( + default_value = "10", + name = "NUM", + help = "Number of blocks to revert" + )] + num: u32, + }, +} diff --git a/parity/cli/tests/config.full.toml b/parity/cli/tests/config.full.toml deleted file mode 100644 index f58fab3d8ad..00000000000 --- a/parity/cli/tests/config.full.toml +++ /dev/null @@ -1,172 +0,0 @@ -[parity] -mode = "last" -mode_timeout = 300 -mode_alarm = 3600 -auto_update = "none" -auto_update_delay = 200 -auto_update_check_frequency = 50 -release_track = "current" -public_node = false -no_download = false -no_consensus = false -no_persistent_txqueue = false - -chain = "homestead" -base_path = "$HOME/.parity" -db_path = "$HOME/.parity/chains" -keys_path = "$HOME/.parity/keys" -identity = "" -light = false -no_hardcoded_sync = false - -[account] -unlock = ["0xdeadbeefcafe0000000000000000000000000000"] -password = ["~/.safe/password.file"] -keys_iterations = 10240 - -[private_tx] -enabled = true -signer = "0xdeadbeefcafe0000000000000000000000000000" -validators = ["0xdeadbeefcafe0000000000000000000000000000"] -passwords = "~/.safe/password.file" -account = "0xdeadbeefcafe0000000000000000000000000000" -sstore_url = "http://localhost:8082" -sstore_threshold = 0 - -[ui] -force = false -disable = false -port = 8180 -interface = "127.0.0.1" -path = "$HOME/.parity/signer" - -[network] -port = 30303 -min_peers = 25 -max_peers = 50 -nat = "any" -id = 1 -bootnodes = [] -discovery = true -warp = true -allow_ips = "all" -snapshot_peers = 0 -max_pending_peers = 64 -no_serve_light = false - -reserved_only = false -reserved_peers = "./path_to_file" - -[rpc] -disable = false -port = 8545 -interface = "local" -cors = ["null"] -apis = ["web3", "eth", "net", "parity", "traces", "rpc", "secretstore"] -hosts = ["none"] -allow_missing_blocks = false - -[websockets] -disable = false -port = 8546 -interface = "local" -origins = ["none"] -apis = ["web3", "eth", "net", "parity", "traces", "rpc", "secretstore"] -hosts = ["none"] - -[ipc] -chmod = "660" -disable = false -path = "$HOME/.parity/jsonrpc.ipc" -apis = ["web3", "eth", "net", "parity", "parity_accounts", "personal", "traces", "rpc", "secretstore"] - -[dapps] -disable = false -port = 8080 -interface = "local" -hosts = ["none"] -path = "$HOME/.parity/dapps" -# authorization: -user = "test_user" -pass = "test_pass" - -[secretstore] -disable = false -disable_http = false -acl_contract = "registry" -service_contract = "none" -service_contract_srv_gen = "none" -service_contract_srv_retr = "none" -service_contract_doc_store = "none" -service_contract_doc_sretr = "none" -server_set_contract = "registry" -nodes = [] -http_interface = "local" -http_port = 8082 -interface = "local" -port = 8083 -path = "$HOME/.parity/secretstore" -cors = ["null"] - -[mining] -author = "0xdeadbeefcafe0000000000000000000000000001" -engine_signer = "0xdeadbeefcafe0000000000000000000000000001" -force_sealing = true -reseal_on_txs = "all" -reseal_min_period = 4000 -reseal_max_period = 60000 -work_queue_size = 20 -relay_set = "cheap" -min_gas_price = 0 -usd_per_tx = "0.0001" -usd_per_eth = "auto" -price_update_period = "hourly" -gas_floor_target = "8000000" -gas_cap = "10000000" -tx_queue_size = 8192 -tx_queue_locals = ["0xdeadbeefcafe0000000000000000000000000000"] -tx_queue_strategy = "gas_factor" -tx_queue_ban_count = 1 -tx_queue_ban_time = 180 #s -tx_gas_limit = "10000000" -tx_time_limit = 100 #ms -tx_queue_no_unfamiliar_locals = false -tx_queue_no_early_reject = false -extra_data = "Parity" -remove_solved = false -notify_work = ["http://localhost:3001"] -refuse_service_transactions = false - -[footprint] -tracing = "auto" -pruning = "auto" -pruning_history = 64 -pruning_memory = 500 -cache_size_db = 64 -cache_size_blocks = 8 -cache_size_queue = 50 -cache_size_state = 25 -cache_size = 128 # Overrides above caches with total size -db_compaction = "ssd" -fat_db = "auto" -scale_verifiers = true -num_verifiers = 6 - -[light] -on_demand_response_time_window = 2 -on_demand_request_backoff_start = 9 -on_demand_request_backoff_max = 15 -on_demand_request_backoff_rounds_max = 100 -on_demand_request_consecutive_failures = 1 - -[snapshots] -disable_periodic = false - -[misc] -logging = "own_tx=trace" -log_file = "/var/log/parity.log" -color = true - -[whisper] -enabled = false -pool_size = 20 diff --git a/parity/cli/tests/config.invalid1.toml b/parity/cli/tests/config.invalid1.toml deleted file mode 100644 index b340da1028a..00000000000 --- a/parity/cli/tests/config.invalid1.toml +++ /dev/null @@ -1,2 +0,0 @@ -[account -unlock = "0x1" diff --git a/parity/cli/tests/config.invalid2.toml b/parity/cli/tests/config.invalid2.toml deleted file mode 100644 index 766dcfb5998..00000000000 --- a/parity/cli/tests/config.invalid2.toml +++ /dev/null @@ -1,4 +0,0 @@ -[account] -unlock = "0x1" -passwd = [] - diff --git a/parity/cli/tests/config.invalid3.toml b/parity/cli/tests/config.invalid3.toml deleted file mode 100644 index a43afe03de7..00000000000 --- a/parity/cli/tests/config.invalid3.toml +++ /dev/null @@ -1,3 +0,0 @@ -[signer] -passwd = [] - diff --git a/parity/cli/tests/config.invalid4.toml b/parity/cli/tests/config.invalid4.toml deleted file mode 100644 index a5429b2baa8..00000000000 --- a/parity/cli/tests/config.invalid4.toml +++ /dev/null @@ -1,2 +0,0 @@ -[account] -invalid = 5 diff --git a/parity/cli/tests/config.stratum_disabled.toml b/parity/cli/tests/config.stratum_disabled.toml deleted file mode 100644 index b7f99af7e3d..00000000000 --- a/parity/cli/tests/config.stratum_disabled.toml +++ /dev/null @@ -1,2 +0,0 @@ -[stratum] -disable = true \ No newline at end of file diff --git a/parity/cli/tests/config.stratum_enabled.toml b/parity/cli/tests/config.stratum_enabled.toml deleted file mode 100644 index 5b46c0c0cc1..00000000000 --- a/parity/cli/tests/config.stratum_enabled.toml +++ /dev/null @@ -1,5 +0,0 @@ -[stratum] -disable = false -interface = "some_interface" -port = 8007 -secret = "Yellow" \ No newline at end of file diff --git a/parity/cli/tests/config.stratum_missing_field.toml b/parity/cli/tests/config.stratum_missing_field.toml deleted file mode 100644 index 7ceed181508..00000000000 --- a/parity/cli/tests/config.stratum_missing_field.toml +++ /dev/null @@ -1 +0,0 @@ -[stratum] \ No newline at end of file diff --git a/parity/cli/tests/config.stratum_missing_section.toml b/parity/cli/tests/config.stratum_missing_section.toml deleted file mode 100644 index 65efa412c85..00000000000 --- a/parity/cli/tests/config.stratum_missing_section.toml +++ /dev/null @@ -1 +0,0 @@ -# No `[stratum]` section \ No newline at end of file diff --git a/parity/cli/tests/config.toml b/parity/cli/tests/config.toml deleted file mode 100644 index 111f09e5c2e..00000000000 --- a/parity/cli/tests/config.toml +++ /dev/null @@ -1,90 +0,0 @@ -[parity] -mode = "dark" -mode_timeout = 15 -mode_alarm = 10 -chain = "./chain.json" -sync_until = 123 - -[account] -unlock = ["0x1", "0x2", "0x3"] -password = ["passwdfile path"] - -[ui] -disable = true - -[network] -warp = false -discovery = true -nat = "any" -min_peers = 10 -max_peers = 20 -max_pending_peers = 30 -snapshot_peers = 40 -allow_ips = "public" - -reserved_only = true -reserved_peers = "./path/to/reserved_peers" - -[websockets] -disable = true -origins = ["none"] - -[rpc] -disable = true -port = 8180 -server_threads = 13 - -[ipc] -apis = ["rpc", "eth"] - -[dapps] -port = 8080 -user = "username" -pass = "password" - -[secretstore] -http_port = 8082 -port = 8083 - -[mining] -author = "0xdeadbeefcafe0000000000000000000000000001" -engine_signer = "0xdeadbeefcafe0000000000000000000000000001" -force_sealing = true -reseal_on_txs = "all" -reseal_min_period = 4000 -reseal_max_period = 60000 -price_update_period = "hourly" -tx_queue_size = 8192 - -[footprint] -tracing = "on" -pruning = "fast" -pruning_history = 64 -cache_size_db = 256 -cache_size_blocks = 16 -cache_size_queue = 100 -cache_size_state = 25 -db_compaction = "ssd" -fat_db = "off" -scale_verifiers = false - -[light] -on_demand_response_time_window = 2 -on_demand_request_backoff_start = 9 -on_demand_request_backoff_max = 15 -on_demand_request_backoff_rounds_max = 10 -on_demand_request_consecutive_failures = 1 - -[snapshots] -disable_periodic = true - -[misc] -logging = "own_tx=trace" -log_file = "/var/log/parity.log" -color = true -ports_shift = 0 -unsafe_expose = false - -[whisper] -enabled = true -pool_size = 50 diff --git a/parity/cli/tests/mod.rs b/parity/cli/tests/mod.rs new file mode 100644 index 00000000000..51c739f288f --- /dev/null +++ b/parity/cli/tests/mod.rs @@ -0,0 +1,2 @@ +#[cfg(test)] +mod test_cli; diff --git a/parity/cli/tests/test_cli.rs b/parity/cli/tests/test_cli.rs new file mode 100644 index 00000000000..0a3865fb5fc --- /dev/null +++ b/parity/cli/tests/test_cli.rs @@ -0,0 +1,61 @@ +use cli::args::Args; +use cli::args::ArgsError; +use cli::globals::Globals; +use cli::parse_cli::ArgsInput; + +#[test] +fn test_override_defaults_with_custom_config() { + let test_config = + Args::generate_default_configuration("test_config.toml", "config_default.toml").unwrap(); + + assert_eq!(test_config.0.sealing_mining.stratum, true); + assert_eq!( + test_config.0.sealing_mining.stratum_interface, + Some("some interface".to_owned()) + ); + assert_eq!(test_config.0.sealing_mining.stratum_port, Some(8007)); + assert_eq!( + test_config.0.sealing_mining.stratum_secret, + Some("Yellow".to_owned()) + ); +} + +#[test] +fn test_overwrite_custom_config_with_raw_flags() { + let mut raw: ArgsInput = Default::default(); + let mut resolved: Args = Default::default(); + + // These are equivalent to the raw arguments that are going to be accepted + raw.globals.sealing_mining.stratum_secret = Some("Changed".to_owned()); + + // In the default config file, there is a config value "Yellow" for the + // same field, which it should ignore because of the presence of the raw + // argument + let (user_defaults, fallback) = + Args::generate_default_configuration("test_config.toml", "config_default.toml").unwrap(); + + resolved.absorb_cli(raw, user_defaults, fallback); + + assert_eq!(resolved.arg_stratum_secret, Some("Changed".to_owned())); +} + +#[test] +fn test_not_accepting_min_peers_bigger_than_max_peers() { + // Setting up defaults + let mut raw: ArgsInput = Default::default(); + let mut resolved: Args = Default::default(); + let (user_defaults, fallback) = + Args::generate_default_configuration("test_config.toml", "config_default.toml").unwrap(); + + raw.globals.networking.min_peers = Some(50); + raw.globals.networking.max_peers = Some(40); + + let output = resolved.absorb_cli(raw, user_defaults, fallback); + + assert_eq!( + output, + Err(ArgsError::PeerConfigurationError( + "max-peers need to be greater than or equal to min-peers".to_owned() + )) + ); +} diff --git a/parity/cli/usage.rs b/parity/cli/usage.rs deleted file mode 100644 index 26b5fa728d8..00000000000 --- a/parity/cli/usage.rs +++ /dev/null @@ -1,774 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of Open Ethereum. - -// Open Ethereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Open Ethereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Open Ethereum. If not, see . - -macro_rules! return_if_parse_error { - ($e:expr) => ( - match $e { - Err(clap_error @ ClapError { kind: ClapErrorKind::ValueValidation, .. }) => { - return Err(clap_error); - }, - - // Otherwise, if $e is ClapErrorKind::ArgumentNotFound or Ok(), - // then convert to Option - _ => $e.ok() - } - ) -} - -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>, 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>) => ( - 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 { - ( - { - $( - 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, - )* - } - )* - } - { - $( - [$group_name: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, - )* - $( - CHECK $check:expr, - )* - )* - } - ) => { - use toml; - use std::{fs, io, process, cmp}; - use std::io::Read; - use parity_version::version; - use clap::{Arg, App, SubCommand, AppSettings, ArgSettings, Error as ClapError, ErrorKind as ClapErrorKind}; - use dir::helpers::replace_home; - use std::ffi::OsStr; - use std::collections::HashMap; - - extern crate textwrap; - extern crate term_size; - use self::textwrap::{Wrapper}; - - const MAX_TERM_WIDTH: usize = 120; - - #[cfg(test)] - use regex::Regex; - - #[derive(Debug)] - pub enum ArgsError { - Clap(ClapError), - Decode(toml::de::Error), - Config(String, io::Error), - PeerConfiguration, - } - - impl ArgsError { - pub fn exit(self) -> ! { - match self { - ArgsError::Clap(e) => e.exit(), - ArgsError::Decode(e) => { - eprintln!("You might have supplied invalid parameters in config file."); - eprintln!("{}", e); - process::exit(2) - }, - ArgsError::Config(path, e) => { - eprintln!("There was an error reading your config file at: {}", path); - eprintln!("{}", e); - process::exit(2) - }, - ArgsError::PeerConfiguration => { - eprintln!("You have supplied `min_peers` > `max_peers`"); - process::exit(2) - } - } - } - } - - impl From for ArgsError { - fn from(e: ClapError) -> Self { - ArgsError::Clap(e) - } - } - - impl From for ArgsError { - fn from(e: toml::de::Error) -> Self { - ArgsError::Decode(e) - } - } - - /// Parsed command line arguments. - #[derive(Debug, PartialEq)] - pub struct Args { - $( - pub $subc: bool, - - $( - pub $subc_subc: bool, - $( - pub $subc_subc_flag: bool, - )* - $( - pub $subc_subc_arg: $($subc_subc_arg_type_tt)+, - )* - )* - - $( - pub $subc_flag: bool, - )* - $( - pub $subc_arg: $($subc_arg_type_tt)+, - )* - )* - - $( - $( - pub $flag: bool, - )* - $( - pub $arg: $($arg_type_tt)+, - )* - )* - } - - impl Default for Args { - fn default() -> Self { - Args { - $( - $subc: Default::default(), - $( - $subc_subc: Default::default(), - $( - $subc_subc_flag: Default::default(), - )* - $( - $subc_subc_arg: Default::default(), - )* - )* - - $( - $subc_flag: Default::default(), - )* - $( - $subc_arg: Default::default(), - )* - )* - - $( - $( - $flag: Default::default(), - )* - $( - $arg: Default::default(), - )* - )* - } - } - } - - #[derive(Default, Debug, PartialEq, Clone, Deserialize)] - struct RawArgs { - $( - $subc: bool, - - $( - $subc_subc: bool, - $( - $subc_subc_flag: bool, - )* - $( - $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, - )* - $( - $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)+> } - ), - )* - )* - } - - impl Args { - - pub fn parse>(command: &[S]) -> Result { - let raw_args = RawArgs::parse(command)?; - - // Skip loading config file if no_config flag is specified - if raw_args.flag_no_config { - return Ok(raw_args.into_args(Config::default())); - } - - 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); - - let args = match (fs::File::open(&config_file), raw_args.arg_config.clone()) { - // Load config file - (Ok(mut file), _) => { - eprintln!("Loading config file from {}", &config_file); - let mut config = String::new(); - file.read_to_string(&mut config).map_err(|e| ArgsError::Config(config_file, e))?; - Ok(raw_args.into_args(Self::parse_config(&config)?)) - }, - // Don't display error in case default config cannot be loaded. - (Err(_), None) => Ok(raw_args.into_args(Config::default())), - // Config set from CLI (fail with error) - (Err(_), Some(ref config_arg)) => { - match presets::preset_config_string(config_arg) { - Ok(s) => Ok(raw_args.into_args(Self::parse_config(&s)?)), - Err(e) => Err(ArgsError::Config(config_file, e)) - } - }, - }?; - - $( - $( - $check(&args)?; - )* - )* - - Ok(args) - } - - #[cfg(test)] - pub fn parse_without_config>(command: &[S]) -> Result { - Self::parse_with_config(command, Config::default()) - } - - #[cfg(test)] - fn parse_with_config>(command: &[S], config: Config) -> Result { - RawArgs::parse(command).map(|raw| raw.into_args(config)).map_err(ArgsError::Clap) - } - - fn parse_config(config: &str) -> Result { - Ok(toml::from_str(config)?) - } - - 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 { - - const TAB: &str = " "; - const TAB_TAB: &str = " "; - - let term_width = match term_size::dimensions() { - None => MAX_TERM_WIDTH, - Some((w, _)) => { - cmp::min(w, MAX_TERM_WIDTH) - } - }; - - let mut help : String = include_str!("./usage_header.txt").to_owned(); - - help.push_str("\n"); - - // Subcommands - let mut subcommands_wrapper = Wrapper::new(term_width).subsequent_indent(TAB); - 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, - )* - ]; - - help.push_str(&subcommands_wrapper.fill( - format!( - "parity [options] {} {} {}\n", - underscore_to_hyphen!(&stringify!($subc)[4..]), - underscore_to_hyphen!(&stringify!($subc_subc)[stringify!($subc).len()+1..]), - subc_subc_usages.join(" ") - ).as_ref()) - ); - )* - - // 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, - )* - ]; - - help.push_str(&subcommands_wrapper.fill( - format!( - "parity [options] {} {}\n", - underscore_to_hyphen!(&stringify!($subc)[4..]), - subc_usages.join(" ") - ).as_ref()) - ); - } - } - )* - - help.push_str("\n"); - - // Arguments and flags - let args_wrapper = Wrapper::new(term_width).initial_indent(TAB_TAB).subsequent_indent(TAB_TAB); - $( - if $group_name != "Legacy Options" { - help.push_str($group_name); help.push_str(":\n"); - $( - help.push_str(&format!("{}{}\n{}\n", - TAB, $flag_usage, - args_wrapper.fill($flag_help) - )); - help.push_str("\n"); - )* - $( - if_option!( - $($arg_type_tt)+, - THEN { - if_option_vec!( - $($arg_type_tt)+, - THEN { - help.push_str(&format!("{}{}\n{}\n", - TAB, $arg_usage, - args_wrapper.fill(format!( - "{} (default: {:?})", - $arg_help, - {let x : inner_option_type!($($arg_type_tt)+)> = $arg_default; x} - ).as_ref()) - )) - } - ELSE { - help.push_str(&format!("{}{}\n{}\n", - TAB, $arg_usage, - args_wrapper.fill(format!( - "{}{}", - $arg_help, - $arg_default.map(|x: inner_option_type!($($arg_type_tt)+)| format!(" (default: {})",x)).unwrap_or("".to_owned()) - ).as_ref()) - )) - } - ) - } - ELSE { - if_vec!( - $($arg_type_tt)+, - THEN { - help.push_str(&format!("{}{}\n{}\n", TAB, $arg_usage, - args_wrapper.fill(format!( - "{} (default: {:?})", - $arg_help, - {let x : $($arg_type_tt)+ = $arg_default; x} - ).as_ref()) - )) - } - ELSE { - help.push_str(&format!("{}{}\n{}\n", TAB, $arg_usage, - args_wrapper.fill(format!( - "{} (default: {})", - $arg_help, - $arg_default - ).as_ref()) - )) - } - ) - } - ); - help.push_str("\n"); - )* - } - )* - help - } - } - - impl RawArgs { - fn into_args(self, config: Config) -> Args { - let mut args = Args::default(); - $( - args.$subc = self.$subc; - - $( - args.$subc_subc = self.$subc_subc; - $( - args.$subc_subc_flag = self.$subc_subc_flag; - )* - $( - 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.$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 - } - - #[allow(unused_variables)] // the submatches of arg-less subcommands aren't used - pub fn parse>(command: &[S]) -> Result { - - let usages = vec![ - $( - $( - usage_with_ident!(stringify!($arg), $arg_usage, $arg_help), - )* - $( - usage_with_ident!(stringify!($flag), $flag_usage, $flag_help), - )* - )* - ]; - - // Hash of subc|subc_subc => Vec - 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::DisableHelpSubcommand) - .max_term_width(MAX_TERM_WIDTH) - .help(Args::print_help().as_ref()) - .args(&usages.iter().map(|u| { - let mut arg = Arg::from_usage(u) - .allow_hyphen_values(true) // Allow for example --allow-ips -10.0.0.0/8 - .global(true) // Argument doesn't have to come before the first subcommand - .hidden(true); // Hide global arguments from the (subcommand) help messages generated by Clap - - if arg.is_set(ArgSettings::Multiple) { - arg = arg.require_delimiter(true); // Multiple values can only be separated by commas, not spaces (#7428) - } - - arg - }).collect::>()) - $( - .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).allow_hyphen_values(true)).collect::>()) - $( - .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).allow_hyphen_values(true)).collect::>()) - ) - )* - ) - )* - .get_matches_from_safe(command.iter().map(|x| OsStr::new(x.as_ref())))?; - - let mut raw_args : RawArgs = Default::default(); - - // Globals - $( - $( - raw_args.$flag = raw_args.$flag || matches.is_present(stringify!($flag)); - )* - $( - if let some @ Some(_) = return_if_parse_error!(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)+)) } - ELSE { value_t!(matches, stringify!($arg), inner_option_type!($($arg_type_tt)+)) } - ) - } - ELSE { - if_vec!( - $($arg_type_tt)+, - THEN { values_t!(matches, stringify!($arg), inner_vec_type!($($arg_type_tt)+)) } - ELSE { value_t!(matches, stringify!($arg), $($arg_type_tt)+) } - ) - } - )) { - raw_args.$arg = some; - } - )* - )* - - // 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 = return_if_parse_error!(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)+)) } - ELSE { value_t!(submatches, stringify!($subc_arg), inner_option_type!($($subc_arg_type_tt)+)) } - ) - } - ELSE { - if_vec!( - $($subc_arg_type_tt)+, - THEN { values_t!(submatches, stringify!($subc_arg), inner_vec_type!($($subc_arg_type_tt)+)) } - ELSE { value_t!(submatches, stringify!($subc_arg), $($subc_arg_type_tt)+) } - ) - } - )); - )* - // 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 = return_if_parse_error!(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)+)) } - ELSE { value_t!(subsubmatches, stringify!($subc_subc_arg), inner_option_type!($($subc_subc_arg_type_tt)+)) } - ) - } - ELSE { - if_vec!( - $($subc_subc_arg_type_tt)+, - THEN { values_t!(subsubmatches, stringify!($subc_subc_arg), inner_vec_type!($($subc_subc_arg_type_tt)+)) } - ELSE { value_t!(subsubmatches, stringify!($subc_subc_arg), $($subc_subc_arg_type_tt)+) } - ) - } - )); - )* - } - 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)); - } - } - } -} diff --git a/parity/configuration.rs b/parity/configuration.rs index d04265c535e..760efed9f0d 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -21,7 +21,7 @@ use std::path::PathBuf; use std::collections::{HashSet, BTreeMap}; use std::iter::FromIterator; use std::cmp; -use cli::{Args, ArgsError}; +use cli::args::{Args, ArgsError}; use hash::keccak; use ethereum_types::{U256, H256, Address}; use parity_version::{version_data, version}; @@ -37,7 +37,7 @@ use verification::queue::VerifierSettings; use rpc::{IpcConfiguration, HttpConfiguration, WsConfiguration}; use parity_rpc::NetworkSettings; use cache::CacheConfig; -use helpers::{to_duration, to_mode, to_block_id, to_u256, to_pending_set, to_price, geth_ipc_path, parity_ipc_path, to_bootnodes, to_addresses, to_address, to_queue_strategy, to_queue_penalization}; +use helpers::{to_duration, to_mode, to_block_id, to_u256, to_pending_set, to_price, parity_ipc_path, to_bootnodes, to_addresses, to_address, to_queue_strategy, to_queue_penalization}; use dir::helpers::{replace_home, replace_home_and_local}; use params::{ResealPolicy, AccountsConfig, GasPricerConfig, MinerExtras, SpecType}; use ethcore_logger::Config as LogConfig; @@ -50,7 +50,7 @@ use types::data_format::DataFormat; use blockchain::{BlockchainCmd, ImportBlockchain, ExportBlockchain, KillBlockchain, ExportState, ResetBlockchain}; use export_hardcoded_sync::ExportHsyncCmd; use presale::ImportWallet; -use account::{AccountCmd, NewAccount, ListAccounts, ImportAccounts, ImportFromGethAccounts}; +use account::{AccountCmd, NewAccount, ListAccounts, ImportAccounts}; use snapshot_cmd::{self, SnapshotCommand}; use network::{IpFilter, NatType}; @@ -61,7 +61,7 @@ pub const ETHERSCAN_ETH_PRICE_ENDPOINT: &str = "https://api.etherscan.io/api?mod #[derive(Debug, PartialEq)] pub enum Cmd { Run(RunCmd), - Version, + // Version, // NOTE: this is automatically handled by structopt Account(AccountCmd), ImportPresaleWallet(ImportWallet), Blockchain(BlockchainCmd), @@ -86,6 +86,7 @@ pub enum Cmd { ExportHardcodedSync(ExportHsyncCmd), } +#[derive(Debug, PartialEq)] pub struct Execute { pub logger: LogConfig, pub cmd: Cmd, @@ -108,7 +109,7 @@ impl Configuration { /// ``` pub fn parse_cli>(command: &[S]) -> Result { let config = Configuration { - args: Args::parse(command)?, + args: Args::parse()?, }; Ok(config) @@ -146,9 +147,7 @@ impl Configuration { return Err("--key-iterations must be non-zero".into()); } - let cmd = if self.args.flag_version { - Cmd::Version - } else if self.args.cmd_signer { + let cmd = if self.args.cmd_signer { let authfile = ::signer::codes_path(&ws_conf.signer_path); if self.args.cmd_signer_new_token { @@ -224,15 +223,6 @@ impl Configuration { unreachable!(); }; Cmd::Account(account_cmd) - } else if self.args.flag_import_geth_keys { - let account_cmd = AccountCmd::ImportFromGeth( - ImportFromGethAccounts { - spec: spec, - to: dirs.keys, - testnet: self.args.flag_testnet - } - ); - Cmd::Account(account_cmd) } else if self.args.cmd_wallet { let presale_cmd = ImportWallet { iterations: key_iterations, @@ -440,7 +430,7 @@ impl Configuration { } fn author(&self) -> Result { - to_address(self.args.arg_etherbase.clone().or(self.args.arg_author.clone())) + to_address(self.args.arg_author.clone()) } fn engine_signer(&self) -> Result { @@ -457,7 +447,7 @@ impl Configuration { } fn cache_config(&self) -> CacheConfig { - match self.args.arg_cache_size.or(self.args.arg_cache) { + match self.args.arg_cache_size{ Some(size) => CacheConfig::new_with_total_cache_size(size), None => CacheConfig::new( self.args.arg_cache_size_db, @@ -477,56 +467,51 @@ impl Configuration { } } - fn chain(&self) -> Result { - let name = if self.args.flag_testnet { - "testnet".to_owned() - } else { - self.args.arg_chain.clone() - }; - + pub fn chain(&self) -> Result { + let name = self.args.arg_chain.clone(); Ok(name.parse()?) } - fn is_dev_chain(&self) -> Result { + pub fn is_dev_chain(&self) -> Result { Ok(self.chain()? == SpecType::Dev) } - fn max_peers(&self) -> u32 { + pub fn max_peers(&self) -> u32 { self.args.arg_max_peers .or(cmp::max(self.args.arg_min_peers, Some(DEFAULT_MAX_PEERS))) .unwrap_or(DEFAULT_MAX_PEERS) as u32 } - fn ip_filter(&self) -> Result { + pub fn ip_filter(&self) -> Result { 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 { + pub fn min_peers(&self) -> u32 { self.args.arg_min_peers .or(cmp::min(self.args.arg_max_peers, Some(DEFAULT_MIN_PEERS))) .unwrap_or(DEFAULT_MIN_PEERS) as u32 } - fn max_pending_peers(&self) -> u32 { + pub fn max_pending_peers(&self) -> u32 { self.args.arg_max_pending_peers as u32 } - fn snapshot_peers(&self) -> u32 { + pub fn snapshot_peers(&self) -> u32 { self.args.arg_snapshot_peers as u32 } - fn work_notify(&self) -> Vec { + pub fn work_notify(&self) -> Vec { 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 { + pub fn accounts_config(&self) -> Result { let cfg = AccountsConfig { iterations: self.args.arg_keys_iterations, refresh_time: self.args.arg_accounts_refresh, - testnet: self.args.flag_testnet, + testnet: false, // FIXME: legacy option, should ideally be deleted password_files: self.args.arg_password.iter().map(|s| replace_home(&self.directories().base, s)).collect(), unlocked_accounts: to_addresses(&self.args.arg_unlock)?, enable_fast_unlock: self.args.flag_fast_unlock, @@ -535,18 +520,19 @@ impl Configuration { Ok(cfg) } - fn stratum_options(&self) -> Result, String> { - if self.args.flag_stratum { + pub fn stratum_options(&self) -> Result, String> { + if self.args.flag_stratum { Ok(Some(stratum::Options { io_path: self.directories().db, listen_addr: self.stratum_interface(), - port: self.args.arg_ports_shift + self.args.arg_stratum_port, + port: self.args.arg_ports_shift + self.args.arg_stratum_port, secret: self.args.arg_stratum_secret.as_ref().map(|s| s.parse::().unwrap_or_else(|_| keccak(s))), })) } else { Ok(None) } } - fn miner_options(&self) -> Result { + + pub fn miner_options(&self) -> Result { let is_dev_chain = self.is_dev_chain()?; if is_dev_chain && self.args.flag_force_sealing && self.args.arg_reseal_min_period == 0 { return Err("Force sealing can't be used with reseal_min_period = 0".into()); @@ -579,7 +565,7 @@ impl Configuration { Ok(options) } - fn pool_limits(&self) -> Result { + pub fn pool_limits(&self) -> Result { let max_count = self.args.arg_tx_queue_size; Ok(pool::Options { @@ -593,7 +579,7 @@ impl Configuration { }) } - fn pool_verification_options(&self) -> Result{ + pub fn pool_verification_options(&self) -> Result{ Ok(pool::verifier::Options { // NOTE min_gas_price and block_gas_limit will be overwritten right after start. minimal_gas_price: U256::from(20_000_000) * 1_000u32, @@ -606,7 +592,7 @@ impl Configuration { }) } - fn secretstore_config(&self) -> Result { + pub fn secretstore_config(&self) -> Result { Ok(SecretStoreConfiguration { enabled: self.secretstore_enabled(), http_enabled: self.secretstore_http_enabled(), @@ -630,7 +616,7 @@ impl Configuration { }) } - fn gas_pricer_config(&self) -> Result { + pub fn gas_pricer_config(&self) -> Result { fn wei_per_gas(usd_per_tx: f32, usd_per_eth: f32) -> U256 { let wei_per_usd: f32 = 1.0e18 / usd_per_eth; let gas_per_tx: f32 = 21000.0; @@ -638,9 +624,7 @@ impl Configuration { U256::from_dec_str(&format!("{:.0}", wei_per_gas)).unwrap() } - if let Some(dec) = self.args.arg_gasprice.as_ref() { - return Ok(GasPricerConfig::Fixed(to_u256(dec)?)); - } else if let Some(dec) = self.args.arg_min_gas_price { + if let Some(dec) = self.args.arg_min_gas_price { return Ok(GasPricerConfig::Fixed(U256::from(dec))); } else if self.chain()? != SpecType::Foundation { return Ok(GasPricerConfig::Fixed(U256::zero())); @@ -673,15 +657,15 @@ impl Configuration { } } - fn extra_data(&self) -> Result { - match self.args.arg_extradata.as_ref().or(self.args.arg_extra_data.as_ref()) { + pub fn extra_data(&self) -> Result { + match 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()), } } - fn init_reserved_nodes(&self) -> Result, String> { + pub fn init_reserved_nodes(&self) -> Result, String> { use std::fs::File; match self.args.arg_reserved_peers { @@ -707,7 +691,7 @@ impl Configuration { } } - fn net_addresses(&self) -> Result<(SocketAddr, Option), String> { + pub fn net_addresses(&self) -> Result<(SocketAddr, Option), String> { let port = self.args.arg_ports_shift + self.args.arg_port; let listen_address = SocketAddr::new(self.interface(&self.args.arg_interface).parse().unwrap(), port); let public_address = if self.args.arg_nat.starts_with("extip:") { @@ -729,7 +713,7 @@ impl Configuration { Ok((listen_address, public_address)) } - fn net_config(&self) -> Result { + pub fn net_config(&self) -> Result { let mut ret = NetworkConfiguration::new(); ret.nat_enabled = self.args.arg_nat == "any" || self.args.arg_nat == "upnp" || self.args.arg_nat == "natpmp"; ret.nat_type = match &self.args.arg_nat[..] { @@ -749,7 +733,7 @@ impl Configuration { Some(Ok(key)) => Some(key), Some(Err(err)) => return Err(err), }; - ret.discovery_enabled = !self.args.flag_no_discovery && !self.args.flag_nodiscover; + ret.discovery_enabled = !self.args.flag_no_discovery; ret.max_peers = self.max_peers(); ret.min_peers = self.min_peers(); ret.snapshot_peers = self.snapshot_peers(); @@ -772,16 +756,12 @@ impl Configuration { Ok(ret) } - fn network_id(&self) -> Option { - self.args.arg_network_id.or(self.args.arg_networkid) + pub fn network_id(&self) -> Option { + self.args.arg_network_id } - fn rpc_apis(&self) -> String { - let mut apis: Vec<&str> = self.args.arg_rpcapi - .as_ref() - .unwrap_or(&self.args.arg_jsonrpc_apis) - .split(",") - .collect(); + pub fn rpc_apis(&self) -> String { + let mut apis: Vec<&str> = self.args.arg_jsonrpc_apis.split(",").collect(); if self.args.flag_geth { apis.insert(0, "personal"); @@ -790,7 +770,7 @@ impl Configuration { apis.join(",") } - fn cors(cors: &str) -> Option> { + pub fn cors(cors: &str) -> Option> { match cors { "none" => return Some(Vec::new()), "*" | "all" | "any" => return None, @@ -800,8 +780,8 @@ impl Configuration { Some(cors.split(',').map(Into::into).collect()) } - fn rpc_cors(&self) -> Option> { - let cors = self.args.arg_rpccorsdomain.clone().unwrap_or_else(|| self.args.arg_jsonrpc_cors.to_owned()); + pub fn rpc_cors(&self) -> Option> { + let cors = self.args.arg_jsonrpc_cors.to_owned(); Self::cors(&cors) } @@ -827,7 +807,7 @@ impl Configuration { Some(hosts) } - fn rpc_hosts(&self) -> Option> { + pub fn rpc_hosts(&self) -> Option> { self.hosts(&self.args.arg_jsonrpc_hosts, &self.rpc_interface()) } @@ -846,14 +826,14 @@ impl Configuration { fn ipc_config(&self) -> Result { let conf = IpcConfiguration { chmod: self.args.arg_ipc_chmod.clone(), - enabled: !(self.args.flag_ipcdisable || self.args.flag_ipc_off || self.args.flag_no_ipc), + enabled: !self.args.flag_no_ipc, socket_addr: self.ipc_path(), apis: { - let mut apis = self.args.arg_ipcapi.clone().unwrap_or(self.args.arg_ipc_apis.clone()); + let mut apis = self.args.arg_ipc_apis.clone(); if self.args.flag_geth { if !apis.is_empty() { - apis.push_str(","); - } + apis.push_str(","); + } apis.push_str("personal"); } apis.parse()? @@ -863,11 +843,11 @@ impl Configuration { Ok(conf) } - fn http_config(&self) -> Result { + pub fn http_config(&self) -> Result { let mut conf = HttpConfiguration::default(); conf.enabled = self.rpc_enabled(); conf.interface = self.rpc_interface(); - conf.port = self.args.arg_ports_shift + self.args.arg_rpcport.unwrap_or(self.args.arg_jsonrpc_port); + conf.port = self.args.arg_ports_shift + self.args.arg_jsonrpc_port; conf.apis = self.rpc_apis().parse()?; conf.hosts = self.rpc_hosts(); conf.cors = self.rpc_cors(); @@ -882,7 +862,7 @@ impl Configuration { Ok(conf) } - fn ws_config(&self) -> Result { + pub fn ws_config(&self) -> Result { let support_token_api = // enabled when not unlocking self.args.arg_unlock.is_none() && self.args.arg_enable_signing_queue; @@ -902,7 +882,7 @@ impl Configuration { Ok(conf) } - fn private_provider_config(&self) -> Result<(ProviderConfig, EncryptorConfig, bool), String> { + pub fn private_provider_config(&self) -> Result<(ProviderConfig, EncryptorConfig, bool), String> { let dirs = self.directories(); let provider_conf = ProviderConfig { validator_accounts: to_addresses(&self.args.arg_private_validators)?, @@ -923,7 +903,7 @@ impl Configuration { Ok((provider_conf, encryptor_conf, self.args.flag_private_enabled)) } - fn snapshot_config(&self) -> Result { + pub fn snapshot_config(&self) -> Result { let mut conf = SnapshotConfiguration::default(); conf.no_periodic = self.args.flag_no_periodic_snapshot; if let Some(threads) = self.args.arg_snapshot_threads { @@ -935,7 +915,7 @@ impl Configuration { Ok(conf) } - fn network_settings(&self) -> Result { + pub fn network_settings(&self) -> Result { let http_conf = self.http_config()?; let net_addresses = self.net_addresses()?; Ok(NetworkSettings { @@ -949,7 +929,7 @@ impl Configuration { }) } - fn update_policy(&self) -> Result { + pub fn update_policy(&self) -> Result { Ok(UpdatePolicy { enable_downloading: !self.args.flag_no_download, require_consensus: !self.args.flag_no_consensus, @@ -972,10 +952,14 @@ impl Configuration { }) } - fn directories(&self) -> Directories { + pub fn directories(&self) -> Directories { let local_path = default_local_path(); - 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 default_data_path = default_data_path(); + let base_path: &str = match &self.args.arg_base_path { + Some(x) => &x, + None => &default_data_path, + }; + let data_path = replace_home("", &(base_path)); 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.arg_db_path.is_none() { @@ -1007,19 +991,15 @@ impl Configuration { } } - fn ipc_path(&self) -> String { - if self.args.flag_geth { - geth_ipc_path(self.args.flag_testnet) - } else { + pub fn ipc_path(&self) -> String { parity_ipc_path( &self.directories().base, - &self.args.arg_ipcpath.clone().unwrap_or(self.args.arg_ipc_path.clone()), + &self.args.arg_ipc_path.clone(), self.args.arg_ports_shift, ) - } } - fn interface(&self, interface: &str) -> String { + pub fn interface(&self, interface: &str) -> String { if self.args.flag_unsafe_expose { return "0.0.0.0".into(); } @@ -1031,24 +1011,24 @@ impl Configuration { }.into() } - fn rpc_interface(&self) -> String { - let rpc_interface = self.args.arg_rpcaddr.clone().unwrap_or(self.args.arg_jsonrpc_interface.clone()); + pub fn rpc_interface(&self) -> String { + let rpc_interface = self.args.arg_jsonrpc_interface.clone(); self.interface(&rpc_interface) } - fn ws_interface(&self) -> String { + pub fn ws_interface(&self) -> String { self.interface(&self.args.arg_ws_interface) } - fn secretstore_interface(&self) -> String { + pub fn secretstore_interface(&self) -> String { self.interface(&self.args.arg_secretstore_interface) } - fn secretstore_http_interface(&self) -> String { + pub fn secretstore_http_interface(&self) -> String { self.interface(&self.args.arg_secretstore_http_interface) } - fn secretstore_cors(&self) -> Option> { + pub fn secretstore_cors(&self) -> Option> { Self::cors(self.args.arg_secretstore_http_cors.as_ref()) } @@ -1100,7 +1080,7 @@ impl Configuration { } fn rpc_enabled(&self) -> bool { - !self.args.flag_jsonrpc_off && !self.args.flag_no_jsonrpc + !self.args.flag_no_jsonrpc } fn ws_enabled(&self) -> bool { @@ -1165,792 +1145,3 @@ fn into_secretstore_service_contract_address(s: Option<&String>) -> Result Ok(Some(SecretStoreContractAddress::Address(a.parse().map_err(|e| format!("{}", e))?))), } } - -#[cfg(test)] -mod tests { - use std::io::Write; - use std::fs::File; - use std::str::FromStr; - - use tempfile::TempDir; - use ethcore::miner::MinerOptions; - use miner::pool::PrioritizationStrategy; - use parity_rpc::NetworkSettings; - use updater::{UpdatePolicy, UpdateFilter, ReleaseTrack}; - use types::ids::BlockId; - use types::data_format::DataFormat; - use account::{AccountCmd, NewAccount, ImportAccounts, ListAccounts}; - use blockchain::{BlockchainCmd, ImportBlockchain, ExportBlockchain, ExportState}; - use cli::Args; - use dir::{Directories, default_hypervisor_path}; - use helpers::{default_network_config}; - use params::SpecType; - use presale::ImportWallet; - use rpc::WsConfiguration; - use rpc_apis::ApiSet; - use run::RunCmd; - - use network::{AllowIP, IpFilter}; - - extern crate ipnetwork; - use self::ipnetwork::IpNetwork; - - use super::*; - - #[derive(Debug, PartialEq)] - struct TestPasswordReader(&'static str); - - fn parse(args: &[&str]) -> Configuration { - Configuration { - args: Args::parse_without_config(args).unwrap(), - } - } - - #[test] - fn test_command_version() { - let args = vec!["parity", "--version"]; - let conf = parse(&args); - assert_eq!(conf.into_command().unwrap().cmd, Cmd::Version); - } - - #[test] - fn test_command_account_new() { - let args = vec!["parity", "account", "new"]; - let conf = parse(&args); - assert_eq!(conf.into_command().unwrap().cmd, Cmd::Account(AccountCmd::New(NewAccount { - iterations: 10240, - path: Directories::default().keys, - password_file: None, - spec: SpecType::default(), - }))); - } - - #[test] - fn test_command_account_list() { - let args = vec!["parity", "account", "list"]; - let conf = parse(&args); - assert_eq!(conf.into_command().unwrap().cmd, Cmd::Account( - AccountCmd::List(ListAccounts { - path: Directories::default().keys, - spec: SpecType::default(), - }) - )); - } - - #[test] - fn test_command_account_import() { - let args = vec!["parity", "account", "import", "my_dir", "another_dir"]; - let conf = parse(&args); - assert_eq!(conf.into_command().unwrap().cmd, Cmd::Account(AccountCmd::Import(ImportAccounts { - from: vec!["my_dir".into(), "another_dir".into()], - to: Directories::default().keys, - spec: SpecType::default(), - }))); - } - - #[test] - fn test_command_wallet_import() { - let args = vec!["parity", "wallet", "import", "my_wallet.json", "--password", "pwd"]; - let conf = parse(&args); - assert_eq!(conf.into_command().unwrap().cmd, Cmd::ImportPresaleWallet(ImportWallet { - iterations: 10240, - path: Directories::default().keys, - wallet_path: "my_wallet.json".into(), - password_file: Some("pwd".into()), - spec: SpecType::default(), - })); - } - - #[test] - fn test_command_blockchain_import() { - let args = vec!["parity", "import", "blockchain.json"]; - let conf = parse(&args); - assert_eq!(conf.into_command().unwrap().cmd, Cmd::Blockchain(BlockchainCmd::Import(ImportBlockchain { - spec: Default::default(), - cache_config: Default::default(), - dirs: Default::default(), - file_path: Some("blockchain.json".into()), - format: Default::default(), - pruning: Default::default(), - pruning_history: 128, - pruning_memory: 64, - compaction: Default::default(), - tracing: Default::default(), - fat_db: Default::default(), - check_seal: true, - with_color: !cfg!(windows), - verifier_settings: Default::default(), - light: false, - max_round_blocks_to_import: 12, - }))); - } - - #[test] - fn test_command_blockchain_export() { - let args = vec!["parity", "export", "blocks", "blockchain.json"]; - let conf = parse(&args); - assert_eq!(conf.into_command().unwrap().cmd, Cmd::Blockchain(BlockchainCmd::Export(ExportBlockchain { - spec: Default::default(), - cache_config: Default::default(), - dirs: Default::default(), - file_path: Some("blockchain.json".into()), - pruning: Default::default(), - pruning_history: 128, - pruning_memory: 64, - format: Default::default(), - compaction: Default::default(), - tracing: Default::default(), - fat_db: Default::default(), - from_block: BlockId::Number(1), - to_block: BlockId::Latest, - check_seal: true, - max_round_blocks_to_import: 12, - }))); - } - - #[test] - fn test_command_state_export() { - let args = vec!["parity", "export", "state", "state.json"]; - let conf = parse(&args); - assert_eq!(conf.into_command().unwrap().cmd, Cmd::Blockchain(BlockchainCmd::ExportState(ExportState { - spec: Default::default(), - cache_config: Default::default(), - dirs: Default::default(), - file_path: Some("state.json".into()), - pruning: Default::default(), - pruning_history: 128, - pruning_memory: 64, - format: Default::default(), - compaction: Default::default(), - tracing: Default::default(), - fat_db: Default::default(), - at: BlockId::Latest, - storage: true, - code: true, - min_balance: None, - max_balance: None, - max_round_blocks_to_import: 12, - }))); - } - - #[test] - fn test_command_blockchain_export_with_custom_format() { - let args = vec!["parity", "export", "blocks", "--format", "hex", "blockchain.json"]; - let conf = parse(&args); - assert_eq!(conf.into_command().unwrap().cmd, Cmd::Blockchain(BlockchainCmd::Export(ExportBlockchain { - spec: Default::default(), - cache_config: Default::default(), - dirs: Default::default(), - file_path: Some("blockchain.json".into()), - pruning: Default::default(), - pruning_history: 128, - pruning_memory: 64, - format: Some(DataFormat::Hex), - compaction: Default::default(), - tracing: Default::default(), - fat_db: Default::default(), - from_block: BlockId::Number(1), - to_block: BlockId::Latest, - check_seal: true, - max_round_blocks_to_import: 12, - }))); - } - - #[test] - fn test_command_signer_new_token() { - let args = vec!["parity", "signer", "new-token"]; - let conf = parse(&args); - let expected = Directories::default().signer; - assert_eq!(conf.into_command().unwrap().cmd, Cmd::SignerToken(WsConfiguration { - enabled: true, - interface: "127.0.0.1".into(), - port: 8546, - apis: ApiSet::UnsafeContext, - origins: Some(vec!["parity://*".into(),"chrome-extension://*".into(), "moz-extension://*".into()]), - hosts: Some(vec![]), - signer_path: expected.into(), - support_token_api: false, - max_connections: 100, - }, LogConfig { - color: !cfg!(windows), - mode: None, - file: None, - } )); - } - - #[test] - fn test_ws_max_connections() { - let args = vec!["parity", "--ws-max-connections", "1"]; - let conf = parse(&args); - - assert_eq!(conf.ws_config().unwrap(), WsConfiguration { - max_connections: 1, - ..Default::default() - }); - } - - #[test] - fn test_run_cmd() { - let args = vec!["parity"]; - let conf = parse(&args); - let mut expected = RunCmd { - allow_missing_blocks: false, - cache_config: Default::default(), - dirs: Default::default(), - spec: Default::default(), - pruning: Default::default(), - pruning_history: 128, - pruning_memory: 64, - daemon: None, - logger_config: Default::default(), - miner_options: Default::default(), - gas_price_percentile: 50, - poll_lifetime: 60, - ws_conf: Default::default(), - http_conf: Default::default(), - ipc_conf: Default::default(), - net_conf: default_network_config(), - network_id: None, - warp_sync: true, - warp_barrier: None, - acc_conf: Default::default(), - gas_pricer_conf: Default::default(), - miner_extras: Default::default(), - update_policy: UpdatePolicy { - enable_downloading: true, - require_consensus: true, - filter: UpdateFilter::Critical, - track: ReleaseTrack::Unknown, - path: default_hypervisor_path(), - max_size: 128 * 1024 * 1024, - max_delay: 100, - frequency: 20, - }, - mode: Default::default(), - tracing: Default::default(), - compaction: Default::default(), - geth_compatibility: false, - experimental_rpcs: false, - net_settings: Default::default(), - secretstore_conf: Default::default(), - private_provider_conf: Default::default(), - private_encryptor_conf: Default::default(), - private_tx_enabled: false, - name: "".into(), - custom_bootnodes: false, - fat_db: Default::default(), - snapshot_conf: Default::default(), - stratum: None, - check_seal: true, - download_old_blocks: true, - verifier_settings: Default::default(), - serve_light: true, - light: false, - no_hardcoded_sync: false, - no_persistent_txqueue: false, - max_round_blocks_to_import: 12, - on_demand_response_time_window: None, - on_demand_request_backoff_start: None, - on_demand_request_backoff_max: None, - on_demand_request_backoff_rounds_max: None, - on_demand_request_consecutive_failures: None, - sync_until: None, - }; - expected.secretstore_conf.enabled = cfg!(feature = "secretstore"); - expected.secretstore_conf.http_enabled = cfg!(feature = "secretstore"); - assert_eq!(conf.into_command().unwrap().cmd, Cmd::Run(expected)); - } - - #[test] - fn should_parse_mining_options() { - // given - let mut mining_options = MinerOptions::default(); - - // when - let conf0 = parse(&["parity"]); - let conf2 = parse(&["parity", "--tx-queue-strategy", "gas_price"]); - - // then - assert_eq!(conf0.miner_options().unwrap(), mining_options); - mining_options.tx_queue_strategy = PrioritizationStrategy::GasPriceOnly; - assert_eq!(conf2.miner_options().unwrap(), mining_options); - } - - #[test] - fn should_fail_on_force_reseal_and_reseal_min_period() { - let conf = parse(&["parity", "--chain", "dev", "--force-sealing", "--reseal-min-period", "0"]); - - assert!(conf.miner_options().is_err()); - } - - #[test] - fn should_parse_updater_options() { - // when - let conf0 = parse(&["parity", "--auto-update", "all", "--no-consensus", "--auto-update-delay", "300"]); - let conf1 = parse(&["parity", "--auto-update=xxx"]); - - // then - assert_eq!(conf0.update_policy().unwrap(), UpdatePolicy { - enable_downloading: true, - require_consensus: false, - filter: UpdateFilter::All, - track: ReleaseTrack::Unknown, - path: default_hypervisor_path(), - max_size: 128 * 1024 * 1024, - max_delay: 300, - frequency: 20, - }); - assert!(conf1.update_policy().is_err()); - } - - #[test] - fn should_parse_network_settings() { - // given - - // when - let conf = parse(&["parity", "--testnet", "--identity", "testname"]); - - // then - assert_eq!(conf.network_settings(), Ok(NetworkSettings { - name: "testname".to_owned(), - chain: "goerli".to_owned(), - is_dev_chain: false, - network_port: 30303, - rpc_enabled: true, - rpc_interface: "127.0.0.1".to_owned(), - rpc_port: 8545, - })); - } - - #[test] - fn should_parse_rpc_settings_with_geth_compatiblity() { - // given - fn assert(conf: Configuration) { - let net = conf.network_settings().unwrap(); - assert_eq!(net.rpc_enabled, true); - assert_eq!(net.rpc_interface, "0.0.0.0".to_owned()); - assert_eq!(net.rpc_port, 8000); - assert_eq!(conf.rpc_cors(), None); - assert_eq!(conf.rpc_apis(), "web3,eth".to_owned()); - } - - // when - let conf1 = parse(&["parity", "-j", - "--jsonrpc-port", "8000", - "--jsonrpc-interface", "all", - "--jsonrpc-cors", "*", - "--jsonrpc-apis", "web3,eth" - ]); - let conf2 = parse(&["parity", "--rpc", - "--rpcport", "8000", - "--rpcaddr", "all", - "--rpccorsdomain", "*", - "--rpcapi", "web3,eth" - ]); - - // then - assert(conf1); - assert(conf2); - } - - #[test] - fn should_parse_rpc_hosts() { - // given - - // when - let conf0 = parse(&["parity"]); - let conf1 = parse(&["parity", "--jsonrpc-hosts", "none"]); - let conf2 = parse(&["parity", "--jsonrpc-hosts", "all"]); - let conf3 = parse(&["parity", "--jsonrpc-hosts", "parity.io,something.io"]); - - // then - assert_eq!(conf0.rpc_hosts(), Some(Vec::new())); - assert_eq!(conf1.rpc_hosts(), Some(Vec::new())); - assert_eq!(conf2.rpc_hosts(), None); - assert_eq!(conf3.rpc_hosts(), Some(vec!["parity.io".into(), "something.io".into()])); - } - - #[test] - fn ensures_sane_http_settings() { - // given incorrect settings - let conf = parse(&["parity", - "--jsonrpc-server-threads=0", - "--jsonrpc-max-payload=0", - ]); - - // then things are adjusted to Just Work. - let http_conf = conf.http_config().unwrap(); - assert_eq!(http_conf.server_threads, 1); - assert_eq!(http_conf.max_payload, 1); - } - - #[test] - fn jsonrpc_threading_defaults() { - let conf = parse(&["parity"]); - let http_conf = conf.http_config().unwrap(); - assert_eq!(http_conf.server_threads, 4); - assert_eq!(http_conf.max_payload, 5); - } - - #[test] - fn should_parse_ui_configuration() { - // 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 conf4 = parse(&["parity", "--ui-path=signer", "--force-ui"]); - - // then - assert_eq!(conf0.directories().signer, "signer".to_owned()); - - assert!(conf1.ws_config().unwrap().hosts.is_some()); - assert_eq!(conf1.ws_config().unwrap().origins, Some(vec!["parity://*".into(), "chrome-extension://*".into(), "moz-extension://*".into()])); - assert_eq!(conf1.directories().signer, "signer".to_owned()); - - assert!(conf2.ws_config().unwrap().hosts.is_some()); - assert_eq!(conf2.directories().signer, "signer".to_owned()); - - assert!(conf3.ws_config().unwrap().hosts.is_some()); - assert_eq!(conf3.directories().signer, "signer".to_owned()); - - assert!(conf4.ws_config().unwrap().hosts.is_some()); - assert_eq!(conf4.directories().signer, "signer".to_owned()); - } - - #[test] - fn should_not_bail_on_empty_line_in_reserved_peers() { - let tempdir = TempDir::new().unwrap(); - let filename = tempdir.path().join("peers"); - File::create(&filename).unwrap().write_all(b" \n\t\n").unwrap(); - let args = vec!["parity", "--reserved-peers", filename.to_str().unwrap()]; - let conf = Configuration::parse_cli(&args).unwrap(); - assert!(conf.init_reserved_nodes().is_ok()); - } - - #[test] - fn should_ignore_comments_in_reserved_peers() { - let tempdir = TempDir::new().unwrap(); - let filename = tempdir.path().join("peers_comments"); - File::create(&filename).unwrap().write_all(b"# Sample comment\nenode://6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@172.0.0.1:30303\n").unwrap(); - let args = vec!["parity", "--reserved-peers", filename.to_str().unwrap()]; - let conf = Configuration::parse_cli(&args).unwrap(); - let reserved_nodes = conf.init_reserved_nodes(); - assert!(reserved_nodes.is_ok()); - assert_eq!(reserved_nodes.unwrap().len(), 1); - } - - #[test] - fn test_dev_preset() { - let args = vec!["parity", "--config", "dev"]; - let conf = Configuration::parse_cli(&args).unwrap(); - match conf.into_command().unwrap().cmd { - Cmd::Run(c) => { - assert_eq!(c.net_settings.chain, "dev"); - assert_eq!(c.gas_pricer_conf, GasPricerConfig::Fixed(0.into())); - assert_eq!(c.miner_options.reseal_min_period, Duration::from_millis(0)); - }, - _ => panic!("Should be Cmd::Run"), - } - } - - #[test] - fn test_mining_preset() { - let args = vec!["parity", "--config", "mining"]; - let conf = Configuration::parse_cli(&args).unwrap(); - match conf.into_command().unwrap().cmd { - Cmd::Run(c) => { - assert_eq!(c.net_conf.min_peers, 50); - assert_eq!(c.net_conf.max_peers, 100); - assert_eq!(c.ipc_conf.enabled, false); - assert_eq!(c.miner_options.force_sealing, true); - assert_eq!(c.miner_options.reseal_on_external_tx, true); - assert_eq!(c.miner_options.reseal_on_own_tx, true); - assert_eq!(c.miner_options.reseal_min_period, Duration::from_millis(4000)); - assert_eq!(c.miner_options.pool_limits.max_count, 8192); - assert_eq!(c.cache_config, CacheConfig::new_with_total_cache_size(1024)); - assert_eq!(c.logger_config.mode.unwrap(), "miner=trace,own_tx=trace"); - }, - _ => panic!("Should be Cmd::Run"), - } - } - - #[test] - fn test_non_standard_ports_preset() { - let args = vec!["parity", "--config", "non-standard-ports"]; - let conf = Configuration::parse_cli(&args).unwrap(); - match conf.into_command().unwrap().cmd { - Cmd::Run(c) => { - assert_eq!(c.net_settings.network_port, 30305); - assert_eq!(c.net_settings.rpc_port, 8645); - }, - _ => panic!("Should be Cmd::Run"), - } - } - - #[test] - fn test_insecure_preset() { - let args = vec!["parity", "--config", "insecure"]; - let conf = Configuration::parse_cli(&args).unwrap(); - match conf.into_command().unwrap().cmd { - Cmd::Run(c) => { - assert_eq!(c.update_policy.require_consensus, false); - assert_eq!(c.net_settings.rpc_interface, "0.0.0.0"); - match c.http_conf.apis { - ApiSet::List(set) => assert_eq!(set, ApiSet::All.list_apis()), - _ => panic!("Incorrect rpc apis"), - } - // "web3,eth,net,personal,parity,parity_set,traces,rpc,parity_accounts"); - assert_eq!(c.http_conf.hosts, None); - }, - _ => panic!("Should be Cmd::Run"), - } - } - - #[test] - fn test_dev_insecure_preset() { - let args = vec!["parity", "--config", "dev-insecure"]; - let conf = Configuration::parse_cli(&args).unwrap(); - match conf.into_command().unwrap().cmd { - Cmd::Run(c) => { - assert_eq!(c.net_settings.chain, "dev"); - assert_eq!(c.gas_pricer_conf, GasPricerConfig::Fixed(0.into())); - assert_eq!(c.miner_options.reseal_min_period, Duration::from_millis(0)); - assert_eq!(c.update_policy.require_consensus, false); - assert_eq!(c.net_settings.rpc_interface, "0.0.0.0"); - match c.http_conf.apis { - ApiSet::List(set) => assert_eq!(set, ApiSet::All.list_apis()), - _ => panic!("Incorrect rpc apis"), - } - // "web3,eth,net,personal,parity,parity_set,traces,rpc,parity_accounts"); - assert_eq!(c.http_conf.hosts, None); - }, - _ => panic!("Should be Cmd::Run"), - } - } - - #[test] - fn test_override_preset() { - let args = vec!["parity", "--config", "mining", "--min-peers=99"]; - let conf = Configuration::parse_cli(&args).unwrap(); - match conf.into_command().unwrap().cmd { - Cmd::Run(c) => { - assert_eq!(c.net_conf.min_peers, 99); - }, - _ => panic!("Should be Cmd::Run"), - } - } - - #[test] - fn test_identity_arg() { - let args = vec!["parity", "--identity", "Somebody"]; - let conf = Configuration::parse_cli(&args).unwrap(); - match conf.into_command().unwrap().cmd { - Cmd::Run(c) => { - assert_eq!(c.name, "Somebody"); - assert!(c.net_conf.client_version.starts_with("OpenEthereum/Somebody/")); - } - _ => panic!("Should be Cmd::Run"), - } - } - - #[test] - fn should_apply_ports_shift() { - // given - - // when - let conf0 = parse(&["parity", "--ports-shift", "1", "--stratum"]); - let conf1 = parse(&["parity", "--ports-shift", "1", "--jsonrpc-port", "8544"]); - - // then - assert_eq!(conf0.net_addresses().unwrap().0.port(), 30304); - assert_eq!(conf0.network_settings().unwrap().network_port, 30304); - assert_eq!(conf0.network_settings().unwrap().rpc_port, 8546); - assert_eq!(conf0.http_config().unwrap().port, 8546); - assert_eq!(conf0.ws_config().unwrap().port, 8547); - assert_eq!(conf0.secretstore_config().unwrap().port, 8084); - assert_eq!(conf0.secretstore_config().unwrap().http_port, 8083); - assert_eq!(conf0.stratum_options().unwrap().unwrap().port, 8009); - - assert_eq!(conf1.net_addresses().unwrap().0.port(), 30304); - assert_eq!(conf1.network_settings().unwrap().network_port, 30304); - assert_eq!(conf1.network_settings().unwrap().rpc_port, 8545); - assert_eq!(conf1.http_config().unwrap().port, 8545); - assert_eq!(conf1.ws_config().unwrap().port, 8547); - assert_eq!(conf1.secretstore_config().unwrap().port, 8084); - assert_eq!(conf1.secretstore_config().unwrap().http_port, 8083); - } - - #[test] - fn should_resolve_external_nat_hosts() { - // Ip works - let conf = parse(&["parity", "--nat", "extip:1.1.1.1"]); - assert_eq!(conf.net_addresses().unwrap().1.unwrap().ip().to_string(), "1.1.1.1"); - assert_eq!(conf.net_addresses().unwrap().1.unwrap().port(), 30303); - - // Ip with port works, port is discarded - let conf = parse(&["parity", "--nat", "extip:192.168.1.1:123"]); - assert_eq!(conf.net_addresses().unwrap().1.unwrap().ip().to_string(), "192.168.1.1"); - assert_eq!(conf.net_addresses().unwrap().1.unwrap().port(), 30303); - - // Hostname works - let conf = parse(&["parity", "--nat", "extip:ethereum.org"]); - assert!(conf.net_addresses().unwrap().1.is_some()); - assert_eq!(conf.net_addresses().unwrap().1.unwrap().port(), 30303); - - // Hostname works, garbage at the end is discarded - let conf = parse(&["parity", "--nat", "extip:ethereum.org:whatever bla bla 123"]); - assert!(conf.net_addresses().unwrap().1.is_some()); - assert_eq!(conf.net_addresses().unwrap().1.unwrap().port(), 30303); - - // Garbage is error - let conf = parse(&["parity", "--nat", "extip:blabla"]); - assert!(conf.net_addresses().is_err()); - } - - #[test] - fn should_expose_all_servers() { - // given - - // when - let conf0 = parse(&["parity", "--unsafe-expose"]); - - // then - assert_eq!(&conf0.network_settings().unwrap().rpc_interface, "0.0.0.0"); - assert_eq!(&conf0.http_config().unwrap().interface, "0.0.0.0"); - assert_eq!(conf0.http_config().unwrap().hosts, None); - assert_eq!(&conf0.ws_config().unwrap().interface, "0.0.0.0"); - assert_eq!(conf0.ws_config().unwrap().hosts, None); - assert_eq!(conf0.ws_config().unwrap().origins, None); - assert_eq!(&conf0.secretstore_config().unwrap().interface, "0.0.0.0"); - assert_eq!(&conf0.secretstore_config().unwrap().http_interface, "0.0.0.0"); - } - - #[test] - fn allow_ips() { - let all = parse(&["parity", "--allow-ips", "all"]); - let private = parse(&["parity", "--allow-ips", "private"]); - let block_custom = parse(&["parity", "--allow-ips", "-10.0.0.0/8"]); - let combo = parse(&["parity", "--allow-ips", "public 10.0.0.0/8 -1.0.0.0/8"]); - let ipv6_custom_public = parse(&["parity", "--allow-ips", "public fc00::/7"]); - let ipv6_custom_private = parse(&["parity", "--allow-ips", "private -fc00::/7"]); - - assert_eq!(all.ip_filter().unwrap(), IpFilter { - predefined: AllowIP::All, - custom_allow: vec![], - custom_block: vec![], - }); - - assert_eq!(private.ip_filter().unwrap(), IpFilter { - predefined: AllowIP::Private, - custom_allow: vec![], - custom_block: vec![], - }); - - assert_eq!(block_custom.ip_filter().unwrap(), IpFilter { - predefined: AllowIP::All, - custom_allow: vec![], - custom_block: vec![IpNetwork::from_str("10.0.0.0/8").unwrap()], - }); - - assert_eq!(combo.ip_filter().unwrap(), IpFilter { - predefined: AllowIP::Public, - custom_allow: vec![IpNetwork::from_str("10.0.0.0/8").unwrap()], - custom_block: vec![IpNetwork::from_str("1.0.0.0/8").unwrap()], - }); - - assert_eq!(ipv6_custom_public.ip_filter().unwrap(), IpFilter { - predefined: AllowIP::Public, - custom_allow: vec![IpNetwork::from_str("fc00::/7").unwrap()], - custom_block: vec![], - }); - - assert_eq!(ipv6_custom_private.ip_filter().unwrap(), IpFilter { - predefined: AllowIP::Private, - custom_allow: vec![], - custom_block: vec![IpNetwork::from_str("fc00::/7").unwrap()], - }); - } - - #[test] - fn should_use_correct_cache_path_if_base_is_set() { - use std::path; - - let std = parse(&["parity"]); - let base = parse(&["parity", "--base-path", "/test"]); - - let base_path = ::dir::default_data_path(); - let local_path = ::dir::default_local_path(); - assert_eq!(std.directories().cache, dir::helpers::replace_home_and_local(&base_path, &local_path, ::dir::CACHE_PATH)); - assert_eq!(path::Path::new(&base.directories().cache), path::Path::new("/test/cache")); - } - - #[test] - fn should_respect_only_max_peers_and_default() { - let args = vec!["parity", "--max-peers=50"]; - let conf = Configuration::parse_cli(&args).unwrap(); - match conf.into_command().unwrap().cmd { - Cmd::Run(c) => { - assert_eq!(c.net_conf.min_peers, 25); - assert_eq!(c.net_conf.max_peers, 50); - }, - _ => panic!("Should be Cmd::Run"), - } - } - - #[test] - fn should_respect_only_max_peers_less_than_default() { - let args = vec!["parity", "--max-peers=5"]; - let conf = Configuration::parse_cli(&args).unwrap(); - match conf.into_command().unwrap().cmd { - Cmd::Run(c) => { - assert_eq!(c.net_conf.min_peers, 5); - assert_eq!(c.net_conf.max_peers, 5); - }, - _ => panic!("Should be Cmd::Run"), - } - } - - #[test] - fn should_respect_only_min_peers_and_default() { - let args = vec!["parity", "--min-peers=5"]; - let conf = Configuration::parse_cli(&args).unwrap(); - match conf.into_command().unwrap().cmd { - Cmd::Run(c) => { - assert_eq!(c.net_conf.min_peers, 5); - assert_eq!(c.net_conf.max_peers, 50); - }, - _ => panic!("Should be Cmd::Run"), - } - } - - #[test] - fn should_respect_only_min_peers_and_greater_than_default() { - let args = vec!["parity", "--min-peers=500"]; - let conf = Configuration::parse_cli(&args).unwrap(); - match conf.into_command().unwrap().cmd { - Cmd::Run(c) => { - assert_eq!(c.net_conf.min_peers, 500); - assert_eq!(c.net_conf.max_peers, 500); - }, - _ => panic!("Should be Cmd::Run"), - } - } - - #[test] - fn should_parse_secretstore_cors() { - // given - - // when - let conf0 = parse(&["parity"]); - let conf1 = parse(&["parity", "--secretstore-http-cors", "*"]); - let conf2 = parse(&["parity", "--secretstore-http-cors", "http://parity.io,http://something.io"]); - - // then - assert_eq!(conf0.secretstore_cors(), Some(vec![])); - assert_eq!(conf1.secretstore_cors(), None); - assert_eq!(conf2.secretstore_cors(), Some(vec!["http://parity.io".into(),"http://something.io".into()])); - } -} diff --git a/parity/deprecated.rs b/parity/deprecated.rs deleted file mode 100644 index 5ca56d57adc..00000000000 --- a/parity/deprecated.rs +++ /dev/null @@ -1,305 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of Open Ethereum. - -// Open Ethereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Open Ethereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Open Ethereum. If not, see . - -use std::fmt; -use cli::Args; - -#[derive(Debug, PartialEq)] -pub enum Deprecated { - DoesNothing(&'static str), - Replaced(&'static str, &'static str), - Removed(&'static str), -} - -impl fmt::Display for Deprecated { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - match *self { - Deprecated::DoesNothing(s) => write!(f, "Option '{}' does nothing. It's on by default.", s), - Deprecated::Replaced(old, new) => write!(f, "Option '{}' is deprecated. Please use '{}' instead.", old, new), - Deprecated::Removed(s) => write!(f, "Option '{}' has been removed and is no longer supported.", s) - } - } -} - -pub fn find_deprecated(args: &Args) -> Vec { - let mut result = vec![]; - - // Removed in 1.6 or before. - - if args.flag_warp { - result.push(Deprecated::DoesNothing("--warp")); - } - - if args.flag_jsonrpc { - result.push(Deprecated::DoesNothing("--jsonrpc")); - } - - if args.flag_rpc { - result.push(Deprecated::DoesNothing("--rpc")); - } - - if args.flag_jsonrpc_off { - result.push(Deprecated::Replaced("--jsonrpc-off", "--no-jsonrpc")); - } - - if args.flag_webapp { - result.push(Deprecated::DoesNothing("--webapp")); - } - - if args.flag_dapps_off { - result.push(Deprecated::Replaced("--dapps-off", "--no-dapps")); - } - - if args.flag_ipcdisable { - result.push(Deprecated::Replaced("--ipcdisable", "--no-ipc")); - } - - if args.flag_ipc_off { - result.push(Deprecated::Replaced("--ipc-off", "--no-ipc")); - } - - if args.arg_etherbase.is_some() { - result.push(Deprecated::Replaced("--etherbase", "--author")); - } - - if args.arg_extradata.is_some() { - result.push(Deprecated::Replaced("--extradata", "--extra-data")); - } - - if args.flag_testnet { - result.push(Deprecated::Replaced("--testnet", "--chain testnet")); - } - - if args.flag_nodiscover { - result.push(Deprecated::Replaced("--nodiscover", "--no-discovery")); - } - - if args.arg_datadir.is_some() { - result.push(Deprecated::Replaced("--datadir", "--base-path")); - } - - if args.arg_networkid.is_some() { - result.push(Deprecated::Replaced("--networkid", "--network-id")); - } - - if args.arg_peers.is_some() { - result.push(Deprecated::Replaced("--peers", "--min-peers")); - } - - if args.arg_nodekey.is_some() { - result.push(Deprecated::Replaced("--nodekey", "--node-key")); - } - - if args.arg_rpcaddr.is_some() { - result.push(Deprecated::Replaced("--rpcaddr", "--jsonrpc-interface")); - } - - if args.arg_rpcport.is_some() { - result.push(Deprecated::Replaced("--rpcport", "--jsonrpc-port")); - } - - if args.arg_rpcapi.is_some() { - result.push(Deprecated::Replaced("--rpcapi", "--jsonrpc-api")); - } - - if args.arg_rpccorsdomain.is_some() { - result.push(Deprecated::Replaced("--rpccorsdomain", "--jsonrpc-cors")); - } - - if args.arg_ipcapi.is_some() { - result.push(Deprecated::Replaced("--ipcapi", "--ipc-apis")); - } - - if args.arg_ipcpath.is_some() { - result.push(Deprecated::Replaced("--ipcpath", "--ipc-path")); - } - - if args.arg_gasprice.is_some() { - result.push(Deprecated::Replaced("--gasprice", "--min-gas-price")); - } - - if args.arg_cache.is_some() { - result.push(Deprecated::Replaced("--cache", "--cache-size")); - } - - // Removed in 1.7. - - if args.arg_dapps_port.is_some() { - result.push(Deprecated::Removed("--dapps-port")); - } - - if args.arg_dapps_interface.is_some() { - result.push(Deprecated::Removed("--dapps-interface")); - } - - if args.arg_dapps_hosts.is_some() { - result.push(Deprecated::Removed("--dapps-hosts")); - } - - if args.arg_dapps_cors.is_some() { - result.push(Deprecated::Removed("--dapps-cors")); - } - - if args.arg_dapps_user.is_some() { - result.push(Deprecated::Removed("--dapps-user")); - } - - if args.arg_dapps_pass.is_some() { - result.push(Deprecated::Removed("--dapps-pass")); - } - - if args.flag_dapps_apis_all { - result.push(Deprecated::Replaced("--dapps-apis-all", "--jsonrpc-apis")); - } - - // Removed in 1.11. - - if args.flag_public_node { - result.push(Deprecated::Removed("--public-node")); - } - - if args.flag_force_ui { - result.push(Deprecated::Removed("--force-ui")); - } - - if args.flag_no_ui { - result.push(Deprecated::Removed("--no-ui")); - } - - if args.flag_ui_no_validation { - result.push(Deprecated::Removed("--ui-no-validation")); - } - - if args.arg_ui_interface.is_some() { - result.push(Deprecated::Removed("--ui-interface")); - } - - if args.arg_ui_hosts.is_some() { - result.push(Deprecated::Removed("--ui-hosts")); - } - - if args.arg_ui_port.is_some() { - result.push(Deprecated::Removed("--ui-port")); - } - - if args.arg_tx_queue_ban_count.is_some() { - result.push(Deprecated::Removed("--tx-queue-ban-count")); - } - - if args.arg_tx_queue_ban_time.is_some() { - result.push(Deprecated::Removed("--tx-queue-ban-time")); - } - - // Removed in 2.0. - - if args.flag_fast_and_loose { - result.push(Deprecated::Removed("--fast-and-loose")); - } - - if args.cmd_dapp { - result.push(Deprecated::Removed("parity dapp")); - } - - if args.arg_dapp_path.is_some() { - result.push(Deprecated::Removed("--dapp-path")); - } - - if args.flag_no_dapps { - result.push(Deprecated::Removed("--no-dapps")); - } - - if args.arg_dapps_path.is_some() { - result.push(Deprecated::Removed("--dapps-path")); - } - - if args.arg_ntp_servers.is_some() { - result.push(Deprecated::Removed("--ntp-servers")); - } - - // Removed in 2.7. - - if args.flag_whisper { - result.push(Deprecated::Removed("--whisper")); - } - - if args.arg_whisper_pool_size.is_some() { - result.push(Deprecated::Removed("--whisper-pool-size")); - } - - if args.arg_jsonrpc_threads.is_some() { - result.push(Deprecated::Removed("--jsonrpc--threads (aka processing_threads)")); - } - - result -} - -#[cfg(test)] -mod tests { - use cli::Args; - use super::{Deprecated, find_deprecated}; - - #[test] - fn test_find_deprecated() { - assert_eq!(find_deprecated(&Args::default()), vec![]); - assert_eq!(find_deprecated(&{ - let mut args = Args::default(); - args.flag_warp = true; - args.flag_jsonrpc = true; - args.flag_rpc = true; - args.flag_jsonrpc_off = true; - args.flag_webapp = true; - args.flag_dapps_off = true; - args.flag_ipcdisable = true; - args.flag_ipc_off = true; - 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.flag_fast_and_loose = true; - args.arg_ntp_servers = Some(Default::default()); - args.flag_whisper = true; - args.arg_whisper_pool_size = Some(Default::default()); - args - }), vec![ - Deprecated::DoesNothing("--warp"), - Deprecated::DoesNothing("--jsonrpc"), - Deprecated::DoesNothing("--rpc"), - Deprecated::Replaced("--jsonrpc-off", "--no-jsonrpc"), - Deprecated::DoesNothing("--webapp"), - Deprecated::Replaced("--dapps-off", "--no-dapps"), - Deprecated::Replaced("--ipcdisable", "--no-ipc"), - Deprecated::Replaced("--ipc-off", "--no-ipc"), - Deprecated::Replaced("--etherbase", "--author"), - Deprecated::Replaced("--extradata", "--extra-data"), - Deprecated::Removed("--dapps-port"), - Deprecated::Removed("--dapps-interface"), - Deprecated::Removed("--dapps-hosts"), - Deprecated::Removed("--dapps-cors"), - Deprecated::Removed("--dapps-user"), - Deprecated::Removed("--dapps-pass"), - Deprecated::Replaced("--dapps-apis-all", "--jsonrpc-apis"), - Deprecated::Removed("--fast-and-loose"), - Deprecated::Removed("--ntp-servers"), - Deprecated::Removed("--whisper"), - Deprecated::Removed("--whisper-pool-size"), - ]); - } -} diff --git a/parity/lib.rs b/parity/lib.rs index f8be172fa0e..fb7d4d1cb82 100644 --- a/parity/lib.rs +++ b/parity/lib.rs @@ -19,8 +19,9 @@ extern crate ansi_term; extern crate docopt; -#[macro_use] +extern crate rust_embed; extern crate clap; +extern crate structopt; extern crate dir; extern crate futures; extern crate atty; @@ -35,7 +36,6 @@ extern crate rustc_hex; extern crate semver; extern crate serde; extern crate serde_json; -#[macro_use] extern crate serde_derive; extern crate toml; @@ -104,8 +104,8 @@ mod blockchain; mod cache; mod cli; mod configuration; +mod test_configuration; mod export_hardcoded_sync; -mod deprecated; mod helpers; mod informant; mod light_helpers; @@ -126,9 +126,8 @@ use std::fs::File; use std::io::BufReader; use std::sync::Arc; -use cli::Args; +// use cli::args::Args; use configuration::{Cmd, Execute}; -use deprecated::find_deprecated; use hash::keccak_buffer; pub use self::configuration::Configuration; @@ -205,7 +204,9 @@ fn execute( let outcome = run::execute(run_cmd, logger, on_client_rq, on_updater_rq)?; Ok(ExecutionAction::Running(outcome)) }, - Cmd::Version => Ok(ExecutionAction::Instant(Some(Args::print_version()))), + + // NOTE: this is handled automatically by structopt + // Cmd::Version => Ok(ExecutionAction::Instant(Some(Args::print_version()))), Cmd::Hash(maybe_file) => print_hash_of(maybe_file).map(|s| ExecutionAction::Instant(Some(s))), Cmd::Account(account_cmd) => account::execute(account_cmd).map(|s| ExecutionAction::Instant(Some(s))), Cmd::ImportPresaleWallet(presale_cmd) => presale::execute(presale_cmd).map(|s| ExecutionAction::Instant(Some(s))), @@ -241,10 +242,5 @@ pub fn start( Cr: Fn(String) + 'static + Send, Rr: Fn() + 'static + Send { - let deprecated = find_deprecated(&conf.args); - for d in deprecated { - println!("{}", d); - } - execute(conf.into_command()?, logger, on_client_rq, on_updater_rq) } diff --git a/parity/main.rs b/parity/main.rs index 0c2b98d02ef..b70af559503 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -186,7 +186,7 @@ fn main_direct(force_can_restart: bool) -> i32 { let mut conf = { let args = std::env::args().collect::>(); - openethereum::Configuration::parse_cli(&args).unwrap_or_else(|e| e.exit()) + openethereum::Configuration::parse_cli(&args).unwrap_or_else(|_| process::exit(2)) }; let logger = setup_log(&conf.logger_config()).unwrap_or_else(|e| { @@ -195,7 +195,6 @@ fn main_direct(force_can_restart: bool) -> i32 { }); if let Some(spec_override) = take_spec_name_override() { - conf.args.flag_testnet = false; conf.args.arg_chain = spec_override; } diff --git a/parity/test_configuration.rs b/parity/test_configuration.rs new file mode 100644 index 00000000000..96dd309160d --- /dev/null +++ b/parity/test_configuration.rs @@ -0,0 +1,1147 @@ +#[cfg(test)] +mod test_configuration{ + use cli::args::Args; + use cli::parse_cli::ArgsInput; + use cli::globals::Globals; + use ethcore_logger::Config as LogConfig; + use configuration::{Configuration, Cmd}; + use std::time::Duration; + use params::{GasPricerConfig}; + use cache::CacheConfig; + + use std::io::Write; + use std::fs::File; + use std::str::FromStr; + + use tempfile::TempDir; + use ethcore::miner::MinerOptions; + use miner::pool::PrioritizationStrategy; + use parity_rpc::NetworkSettings; + use updater::{UpdatePolicy, UpdateFilter, ReleaseTrack}; + use types::ids::BlockId; + use types::data_format::DataFormat; + use account::{AccountCmd, NewAccount, ImportAccounts, ListAccounts}; + use blockchain::{BlockchainCmd, ImportBlockchain, ExportBlockchain, ExportState}; + use dir::{Directories, default_hypervisor_path}; + use helpers::{default_network_config}; + use params::SpecType; + use presale::ImportWallet; + use rpc::WsConfiguration; + use rpc_apis::ApiSet; + use run::RunCmd; + + use network::{AllowIP, IpFilter}; + + extern crate ipnetwork; + use self::ipnetwork::IpNetwork; + + use super::*; + + + fn intialize_with_out_of_the_box_defaults() -> (Args, ArgsInput, Globals, Globals) { + let raw: ArgsInput = Default::default(); + let resolved: Args = Default::default(); + let (user_defaults, fallback) = Args::generate_default_configuration( + "config_default.toml", + "config_default.toml" + ).unwrap(); + + (resolved, raw, user_defaults, fallback) + } + + #[test] + fn test_subcommand_account_new() { + let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + conf.cmd_account = true; + conf.cmd_account_new = true; + + let conf = Configuration { + args: conf, + }; + + let conf: Cmd = conf.into_command().unwrap().cmd; + + let cmd_arg: Cmd = Cmd::Account( + AccountCmd::New(NewAccount{ + iterations: 10240, + path: Directories::default().keys, + password_file: None, + spec: SpecType::default(), + })); + + assert_eq!(conf, cmd_arg); + + } + + #[test] + fn test_command_account_list() { + let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + + conf.cmd_account = true; + conf.cmd_account_list = true; + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + let conf = Configuration { + args: conf, + }; + + let conf: Cmd = conf.into_command().unwrap().cmd; + + let cmd_arg: Cmd = Cmd::Account( + AccountCmd::List(ListAccounts { + path: Directories::default().keys, + spec: SpecType::default(), + })); + + assert_eq!(conf, cmd_arg); + + } + + #[test] + fn test_command_account_import() { + + let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + conf.cmd_account = true; + conf.cmd_account_import = true; + conf.arg_account_import_path = Some(vec!["my_dir".into(), "another_dir".into()]); + + let conf = Configuration { + args: conf, + }; + + let conf: Cmd = conf.into_command().unwrap().cmd; + + let cmd_arg: Cmd = Cmd::Account(AccountCmd::Import(ImportAccounts { + from: vec!["my_dir".into(), "another_dir".into()], + to: Directories::default().keys, + spec: SpecType::default(), + })); + + assert_eq!(conf, cmd_arg); + } + + #[test] + fn test_command_wallet_import() { + let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + conf.cmd_wallet = true; + conf.cmd_wallet_import = true; + conf.arg_wallet_import_path = Some("my_wallet.json".to_owned()); + conf.arg_password = vec!["pwd".into()]; + + let conf = Configuration { + args: conf, + }; + + let conf: Cmd = conf.into_command().unwrap().cmd; + + let cmd_arg = Cmd::ImportPresaleWallet(ImportWallet { + iterations: 10240, + path: Directories::default().keys, + wallet_path: "my_wallet.json".into(), + password_file: Some("pwd".into()), + spec: SpecType::default(), + }); + + assert_eq!(conf, cmd_arg); + } + + #[test] + fn test_command_blockchain_import() { + + let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + conf.cmd_import = true; + conf.arg_import_file = Some("blockchain.json".to_owned()); + + let conf = Configuration { + args: conf, + }; + + let conf: Cmd = conf.into_command().unwrap().cmd; + + let cmd_arg = Cmd::Blockchain(BlockchainCmd::Import(ImportBlockchain { + spec: Default::default(), + cache_config: Default::default(), + dirs: Default::default(), + file_path: Some("blockchain.json".into()), + format: Default::default(), + pruning: Default::default(), + pruning_history: 128, + pruning_memory: 64, + compaction: Default::default(), + tracing: Default::default(), + fat_db: Default::default(), + check_seal: true, + with_color: !cfg!(windows), + verifier_settings: Default::default(), + light: false, + max_round_blocks_to_import: 12, + })); + + assert_eq!(conf, cmd_arg); + } + + #[test] + fn test_command_blockchain_export() { + let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + conf.cmd_export = true; + conf.cmd_export_blocks = true; + conf.arg_export_blocks_from = "1".to_owned(); + conf.arg_export_blocks_to = "latest".to_owned(); + conf.arg_export_blocks_file = Some("blockchain.json".to_owned()); + + let conf = Configuration { + args: conf, + }; + + let conf: Cmd = conf.into_command().unwrap().cmd; + + let cmd_arg = Cmd::Blockchain(BlockchainCmd::Export(ExportBlockchain { + spec: Default::default(), + cache_config: Default::default(), + dirs: Default::default(), + file_path: Some("blockchain.json".into()), + pruning: Default::default(), + pruning_history: 128, + pruning_memory: 64, + format: Default::default(), + compaction: Default::default(), + tracing: Default::default(), + fat_db: Default::default(), + from_block: BlockId::Number(1), + to_block: BlockId::Latest, + check_seal: true, + max_round_blocks_to_import: 12, + })); + assert_eq!(conf, cmd_arg); + } + #[test] + fn test_command_state_export() { + let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + conf.cmd_export = true; + conf.cmd_export_state = true; + conf.arg_export_state_at = "latest".to_owned(); + conf.arg_export_state_min_balance = None; + conf.arg_export_state_max_balance = None; + conf.arg_export_state_file = Some("state.json".to_owned()); + + let conf = Configuration { + args: conf, + }; + + let conf: Cmd = conf.into_command().unwrap().cmd; + + let cmd_arg = Cmd::Blockchain(BlockchainCmd::ExportState(ExportState { + spec: Default::default(), + cache_config: Default::default(), + dirs: Default::default(), + file_path: Some("state.json".into()), + pruning: Default::default(), + pruning_history: 128, + pruning_memory: 64, + format: Default::default(), + compaction: Default::default(), + tracing: Default::default(), + fat_db: Default::default(), + at: BlockId::Latest, + storage: true, + code: true, + min_balance: None, + max_balance: None, + max_round_blocks_to_import: 12, + })); + + assert_eq!(conf, cmd_arg); + } + + #[test] + fn test_command_blockchain_export_with_custom_format() { + + let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + conf.cmd_export = true; + conf.cmd_export_blocks = true; + conf.arg_export_blocks_from = "1".to_owned(); + conf.arg_export_blocks_to = "latest".to_owned(); + conf.arg_export_blocks_format = Some("hex".to_owned()); + conf.arg_export_blocks_file = Some("blockchain.json".to_owned()); + + let conf = Configuration { + args: conf, + }; + + let conf: Cmd = conf.into_command().unwrap().cmd; + + let cmd_arg = Cmd::Blockchain(BlockchainCmd::Export(ExportBlockchain { + spec: Default::default(), + cache_config: Default::default(), + dirs: Default::default(), + file_path: Some("blockchain.json".into()), + pruning: Default::default(), + pruning_history: 128, + pruning_memory: 64, + format: Some(DataFormat::Hex), + compaction: Default::default(), + tracing: Default::default(), + fat_db: Default::default(), + from_block: BlockId::Number(1), + to_block: BlockId::Latest, + check_seal: true, + max_round_blocks_to_import: 12, + })); + assert_eq!(conf, cmd_arg); + } + #[test] + fn test_command_signer_new_token() { + + let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + conf.cmd_signer = true; + conf.cmd_signer_new_token = true; + + let conf = Configuration { + args: conf, + }; + + let conf: Cmd = conf.into_command().unwrap().cmd; + + let expected = Directories::default().signer; + let cmd_arg = Cmd::SignerToken(WsConfiguration { + enabled: true, + interface: "127.0.0.1".into(), + port: 8546, + apis: ApiSet::UnsafeContext, + origins: Some(vec!["parity://*".into(),"chrome-extension://*".into(), "moz-extension://*".into()]), + hosts: Some(vec![]), + signer_path: expected.into(), + support_token_api: false, + max_connections: 100, + }, LogConfig { + color: !cfg!(windows), + mode: None, + file: None, + } ); + + assert_eq!(conf, cmd_arg); + } + + #[test] + fn test_ws_max_connections() { + let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + conf.arg_ws_max_connections = 1; + + let conf = Configuration { + args: conf, + }; + + assert_eq!(conf.ws_config().unwrap(), WsConfiguration { + max_connections: 1, + ..Default::default() + }); + } + + #[test] + fn test_run_cmd() { + let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + let conf = Configuration { + args: conf, + }; + + let conf = conf.into_command().unwrap().cmd; + + let mut expected = RunCmd { + allow_missing_blocks: false, + cache_config: Default::default(), + dirs: Default::default(), + spec: Default::default(), + pruning: Default::default(), + pruning_history: 128, + pruning_memory: 64, + daemon: None, + logger_config: Default::default(), + miner_options: Default::default(), + gas_price_percentile: 50, + poll_lifetime: 60, + ws_conf: Default::default(), + http_conf: Default::default(), + ipc_conf: Default::default(), + net_conf: default_network_config(), + network_id: None, + warp_sync: true, + warp_barrier: None, + acc_conf: Default::default(), + gas_pricer_conf: Default::default(), + miner_extras: Default::default(), + update_policy: UpdatePolicy { + enable_downloading: true, + require_consensus: true, + filter: UpdateFilter::Critical, + track: ReleaseTrack::Unknown, + path: default_hypervisor_path(), + max_size: 128 * 1024 * 1024, + max_delay: 100, + frequency: 20, + }, + mode: Default::default(), + tracing: Default::default(), + compaction: Default::default(), + geth_compatibility: false, + experimental_rpcs: false, + net_settings: Default::default(), + secretstore_conf: Default::default(), + private_provider_conf: Default::default(), + private_encryptor_conf: Default::default(), + private_tx_enabled: false, + name: "".into(), + custom_bootnodes: false, + fat_db: Default::default(), + snapshot_conf: Default::default(), + stratum: None, + check_seal: true, + download_old_blocks: true, + verifier_settings: Default::default(), + serve_light: true, + light: false, + no_hardcoded_sync: false, + no_persistent_txqueue: false, + max_round_blocks_to_import: 12, + on_demand_response_time_window: None, + on_demand_request_backoff_start: None, + on_demand_request_backoff_max: None, + on_demand_request_backoff_rounds_max: None, + on_demand_request_consecutive_failures: None, + }; + expected.secretstore_conf.enabled = cfg!(feature = "secretstore"); + expected.secretstore_conf.http_enabled = cfg!(feature = "secretstore"); + + assert_eq!(conf, Cmd::Run(expected)); + } + + #[test] + fn should_parse_mining_options() { + // given + let mut mining_options = MinerOptions::default(); + + // setting up 2 separate configs + let (mut conf0, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf0.absorb_cli(raw, user_defaults, fallback).unwrap(); // default config + + let mut conf2 = conf0.clone(); + conf2.arg_tx_queue_strategy = "gas_price".to_owned(); // modified config + + let conf0 = Configuration { + args: conf0, + }; + + let conf2 = Configuration { + args: conf2, + }; + + // then + assert_eq!(conf0.miner_options().unwrap(), mining_options); + mining_options.tx_queue_strategy = PrioritizationStrategy::GasPriceOnly; + assert_eq!(conf2.miner_options().unwrap(), mining_options); + } + + #[test] + fn should_fail_on_force_reseal_and_reseal_min_period() { + let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + conf.arg_chain = "dev".to_owned(); + conf.flag_force_sealing = true; + conf.arg_reseal_min_period = 0; + + let conf = Configuration { + args: conf, + }; + + assert!(conf.miner_options().is_err()); + } + + #[test] + fn should_parse_updater_options() { + let (mut conf0, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf0.absorb_cli(raw, user_defaults, fallback).unwrap(); + + conf0.arg_auto_update = "all".to_owned(); + conf0.arg_auto_update_delay = 300; + conf0.flag_no_consensus = true; + + let conf0 = Configuration { + args: conf0, + }; + + assert_eq!(conf0.update_policy().unwrap(), UpdatePolicy { + enable_downloading: true, + require_consensus: false, + filter: UpdateFilter::All, + track: ReleaseTrack::Unknown, + path: default_hypervisor_path(), + max_size: 128 * 1024 * 1024, + max_delay: 300, + frequency: 20, + }); + } + + #[test] + fn should_parse_network_settings() { + let (mut conf0, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf0.absorb_cli(raw, user_defaults, fallback).unwrap(); + + conf0.arg_identity = "testname".to_owned(); + conf0.arg_chain = "goerli".to_owned(); + + let conf0 = Configuration { + args: conf0, + }; + + // then + assert_eq!(conf0.network_settings(), Ok(NetworkSettings { + name: "testname".to_owned(), + chain: "goerli".to_owned(), + is_dev_chain: false, + network_port: 30303, + rpc_enabled: true, + rpc_interface: "127.0.0.1".to_owned(), + rpc_port: 8545, + })); + } + + #[test] + fn should_parse_rpc_settings_with_geth_compatiblity() { + // given + fn assert(conf: Configuration) { + let net = conf.network_settings().unwrap(); + assert_eq!(net.rpc_enabled, true); + assert_eq!(net.rpc_interface, "0.0.0.0".to_owned()); + assert_eq!(net.rpc_port, 8000); + assert_eq!(conf.rpc_cors(), None); + assert_eq!(conf.rpc_apis(), "web3,eth".to_owned()); + } + + let (mut conf0, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf0.absorb_cli(raw, user_defaults, fallback).unwrap(); + + let conf2 = conf0.clone(); + + conf0.arg_jsonrpc_port = 8000; + conf0.arg_jsonrpc_interface = "all".to_owned(); + conf0.arg_jsonrpc_cors = "*".to_owned(); + conf0.arg_jsonrpc_apis = "web3,eth".to_owned(); + + let conf0 = Configuration { + args: conf0, + }; + assert(conf0); + } + + #[test] + fn should_parse_rpc_hosts() { + // given + let (mut conf0, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf0.absorb_cli(raw, user_defaults, fallback).unwrap(); + + let mut conf1 = conf0.clone(); + let mut conf2 = conf0.clone(); + let mut conf3 = conf0.clone(); + + conf1.arg_jsonrpc_hosts = "none".to_owned(); + conf2.arg_jsonrpc_hosts = "all".to_owned(); + conf3.arg_jsonrpc_hosts = "parity.io,something.io".to_owned(); + + let conf0 = Configuration { + args: conf0, + }; + + let conf1 = Configuration { + args: conf1, + }; + let conf2 = Configuration { + args: conf2, + }; + let conf3 = Configuration { + args: conf3, + }; + // then + assert_eq!(conf0.rpc_hosts(), Some(Vec::new())); + assert_eq!(conf1.rpc_hosts(), Some(Vec::new())); + assert_eq!(conf2.rpc_hosts(), None); + assert_eq!(conf3.rpc_hosts(), Some(vec!["parity.io".into(), "something.io".into()])); + } + + #[test] + fn should_respect_only_min_peers_and_default() { + let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + conf.arg_min_peers = Some(5); + + let conf = Configuration{ + args: conf, + }; + + match conf.into_command().unwrap().cmd { + Cmd::Run(c) => { + assert_eq!(c.net_conf.min_peers, 5); + assert_eq!(c.net_conf.max_peers, 50); + }, + _ => panic!("Should be Cmd::Run"), + } + } + + #[test] + fn should_respect_only_min_peers_and_greater_than_default() { + let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + conf.arg_min_peers = Some(500); + + let conf = Configuration{ + args: conf, + }; + + match conf.into_command().unwrap().cmd { + Cmd::Run(c) => { + assert_eq!(c.net_conf.min_peers, 500); + assert_eq!(c.net_conf.max_peers, 500); + }, + _ => panic!("Should be Cmd::Run"), + } + } + + #[test] + fn should_parse_secretstore_cors() { + let (mut conf0, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf0.absorb_cli(raw, user_defaults, fallback).unwrap(); + + let mut conf1 = conf0.clone(); + let mut conf2 = conf0.clone(); + + conf1.arg_secretstore_http_cors = "*".to_owned(); + conf2.arg_secretstore_http_cors = "http://parity.io,http://something.io".to_owned(); + + let conf0 = Configuration{ + args: conf0, + }; + + let conf1 = Configuration{ + args: conf1, + }; + + let conf2 = Configuration{ + args: conf2, + }; + + // then + assert_eq!(conf0.secretstore_cors(), Some(vec![])); + assert_eq!(conf1.secretstore_cors(), None); + assert_eq!(conf2.secretstore_cors(), Some(vec!["http://parity.io".into(),"http://something.io".into()])); + } + + #[test] + fn ensures_sane_http_settings() { + let (mut conf0, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf0.absorb_cli(raw, user_defaults, fallback).unwrap(); + + conf0.arg_jsonrpc_server_threads = Some(0); + conf0.arg_jsonrpc_max_payload = Some(0); + + let conf0 = Configuration { + args: conf0, + }; + + // then things are adjusted to Just Work. + let http_conf = conf0.http_config().unwrap(); + assert_eq!(http_conf.server_threads, 1); + assert_eq!(http_conf.max_payload, 1); + } + + #[test] + fn jsonrpc_threading_defaults() { + + let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + assert_eq!(conf.arg_jsonrpc_server_threads, Some(4)); + } + + #[test] + fn test_dev_preset() { + + let raw: ArgsInput = Default::default(); + let mut conf: Args = Default::default(); + + let (user_defaults, fallback) = Args::generate_default_configuration( + "config_dev.toml", + "config_default.toml" + ).unwrap(); + + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + let conf = Configuration { + args: conf, + }; + + match conf.into_command().unwrap().cmd { + Cmd::Run(c) => { + assert_eq!(c.net_settings.chain, "dev"); + assert_eq!(c.gas_pricer_conf, GasPricerConfig::Fixed(0.into())); + assert_eq!(c.miner_options.reseal_min_period, Duration::from_millis(0)); + }, + _ => panic!("Should be Cmd::Run"), + } + } + + #[test] + fn test_mining_preset() { + + let raw: ArgsInput = Default::default(); + let mut conf: Args = Default::default(); + + let (user_defaults, fallback) = Args::generate_default_configuration( + "config_mining.toml", + "config_default.toml" + ).unwrap(); + + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + let conf = Configuration { + args: conf, + }; + + match conf.into_command().unwrap().cmd { + Cmd::Run(c) => { + assert_eq!(c.net_conf.min_peers, 50); + assert_eq!(c.net_conf.max_peers, 100); + assert_eq!(c.ipc_conf.enabled, false); + assert_eq!(c.miner_options.force_sealing, true); + assert_eq!(c.miner_options.reseal_on_external_tx, true); + assert_eq!(c.miner_options.reseal_on_own_tx, true); + assert_eq!(c.miner_options.reseal_min_period, Duration::from_millis(4000)); + assert_eq!(c.miner_options.pool_limits.max_count, 8192); + assert_eq!(c.cache_config, CacheConfig::new_with_total_cache_size(1024)); + assert_eq!(c.logger_config.mode.unwrap(), "miner=trace,own_tx=trace"); + }, + _ => panic!("Should be Cmd::Run"), + } + } + + #[test] + fn test_non_standard_ports_preset() { + let raw: ArgsInput = Default::default(); + let mut conf: Args = Default::default(); + + let (user_defaults, fallback) = Args::generate_default_configuration( + "config_non_standard_ports.toml", + "config_default.toml" + ).unwrap(); + + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + let conf = Configuration { + args: conf, + }; + + match conf.into_command().unwrap().cmd { + Cmd::Run(c) => { + assert_eq!(c.net_settings.network_port, 30305); + assert_eq!(c.net_settings.rpc_port, 8645); + }, + _ => panic!("Should be Cmd::Run"), + } + } + + #[test] + fn test_insecure_preset() { + + let raw: ArgsInput = Default::default(); + let mut conf: Args = Default::default(); + + let (user_defaults, fallback) = Args::generate_default_configuration( + "config_insecure.toml", + "config_default.toml" + ).unwrap(); + + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + let conf = Configuration { + args: conf, + }; + + match conf.into_command().unwrap().cmd { + Cmd::Run(c) => { + assert_eq!(c.update_policy.require_consensus, false); + assert_eq!(c.net_settings.rpc_interface, "0.0.0.0"); + match c.http_conf.apis { + ApiSet::List(set) => assert_eq!(set, ApiSet::All.list_apis()), + _ => panic!("Incorrect rpc apis"), + } +; + assert_eq!(c.http_conf.hosts, None); + }, + _ => panic!("Should be Cmd::Run"), + } + } + + #[test] + fn test_dev_insecure_preset() { + + let raw: ArgsInput = Default::default(); + let mut conf: Args = Default::default(); + + let (user_defaults, fallback) = Args::generate_default_configuration( + "config_dev_insecure.toml", + "config_default.toml" + ).unwrap(); + + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + let conf = Configuration { + args: conf, + }; + + match conf.into_command().unwrap().cmd { + Cmd::Run(c) => { + assert_eq!(c.net_settings.chain, "dev"); + assert_eq!(c.gas_pricer_conf, GasPricerConfig::Fixed(0.into())); + assert_eq!(c.miner_options.reseal_min_period, Duration::from_millis(0)); + assert_eq!(c.update_policy.require_consensus, false); + assert_eq!(c.net_settings.rpc_interface, "0.0.0.0"); + match c.http_conf.apis { + ApiSet::List(set) => assert_eq!(set, ApiSet::All.list_apis()), + _ => panic!("Incorrect rpc apis"), + } + // "web3,eth,net,personal,parity,parity_set,traces,rpc,parity_accounts"); + assert_eq!(c.http_conf.hosts, None); + }, + _ => panic!("Should be Cmd::Run"), + } + } + + #[test] + fn test_override_preset() { + + let mut raw: ArgsInput = Default::default(); + let mut conf: Args = Default::default(); + + raw.globals.networking.min_peers = Some(99); + + let (user_defaults, fallback) = Args::generate_default_configuration( + "config_mining.toml", + "config_default.toml" + ).unwrap(); + + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + let conf = Configuration { + args: conf, + }; + + match conf.into_command().unwrap().cmd { + Cmd::Run(c) => { + assert_eq!(c.net_conf.min_peers, 99); + }, + _ => panic!("Should be Cmd::Run"), + } + } + + #[test] + fn test_identity_arg() { + let (mut conf0, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf0.absorb_cli(raw, user_defaults, fallback).unwrap(); + + conf0.arg_identity = "Somebody".to_owned(); + + let conf0 = Configuration { + args: conf0 + }; + + match conf0.into_command().unwrap().cmd { + Cmd::Run(c) => { + assert_eq!(c.name, "Somebody"); + assert!(c.net_conf.client_version.starts_with("OpenEthereum/Somebody/")); + } + _ => panic!("Should be Cmd::Run"), + } + } + + #[test] + fn should_apply_ports_shift() { + // give + let (mut conf0, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf0.absorb_cli(raw, user_defaults, fallback).unwrap(); + + let mut conf1 = conf0.clone(); + + conf0.arg_ports_shift = 1; + conf0.flag_stratum = true; + + conf1.arg_ports_shift = 1; + conf1.arg_jsonrpc_port = 8544; + + let conf0 = Configuration { + args: conf0 + }; + + let conf1 = Configuration { + args: conf1 + }; + + assert_eq!(conf0.net_addresses().unwrap().0.port(), 30304); + assert_eq!(conf0.network_settings().unwrap().network_port, 30304); + assert_eq!(conf0.network_settings().unwrap().rpc_port, 8546); + assert_eq!(conf0.http_config().unwrap().port, 8546); + assert_eq!(conf0.ws_config().unwrap().port, 8547); + assert_eq!(conf0.secretstore_config().unwrap().port, 8084); + assert_eq!(conf0.secretstore_config().unwrap().http_port, 8083); + assert_eq!(conf0.stratum_options().unwrap().unwrap().port, 8009); + + assert_eq!(conf1.net_addresses().unwrap().0.port(), 30304); + assert_eq!(conf1.network_settings().unwrap().network_port, 30304); + assert_eq!(conf1.network_settings().unwrap().rpc_port, 8545); + assert_eq!(conf1.http_config().unwrap().port, 8545); + assert_eq!(conf1.ws_config().unwrap().port, 8547); + assert_eq!(conf1.secretstore_config().unwrap().port, 8084); + assert_eq!(conf1.secretstore_config().unwrap().http_port, 8083); + } + + #[test] + fn should_resolve_external_nat_hosts() { + + let (mut conf0, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf0.absorb_cli(raw, user_defaults, fallback).unwrap(); + + let mut conf1 = conf0.clone(); + let mut conf2 = conf0.clone(); + let mut conf3 = conf0.clone(); + let mut conf4 = conf0.clone(); + + conf0.arg_nat = "extip:1.1.1.1".to_owned(); + + let conf0 = Configuration { + args: conf0 + }; + + conf1.arg_nat = "extip:192.168.1.1:123".to_owned(); + let conf1 = Configuration { + args: conf1 + }; + + conf2.arg_nat = "extip:ethereum.org".to_owned(); + let conf2 = Configuration { + args: conf2 + }; + + conf3.arg_nat = "extip:ethereum.org:whatever bla bla 123".to_owned(); + let conf3 = Configuration { + args: conf3 + }; + + conf4.arg_nat = "extip:blabla".to_owned(); + let conf4 = Configuration { + args: conf4 + }; + // Ip works + assert_eq!(conf0.net_addresses().unwrap().1.unwrap().ip().to_string(), "1.1.1.1"); + assert_eq!(conf0.net_addresses().unwrap().1.unwrap().port(), 30303); + + // Ip with port works, port is discarded + assert_eq!(conf1.net_addresses().unwrap().1.unwrap().ip().to_string(), "192.168.1.1"); + assert_eq!(conf1.net_addresses().unwrap().1.unwrap().port(), 30303); + + // Hostname works + assert!(conf2.net_addresses().unwrap().1.is_some()); + assert_eq!(conf2.net_addresses().unwrap().1.unwrap().port(), 30303); + + // Hostname works, garbage at the end is discarded + assert!(conf3.net_addresses().unwrap().1.is_some()); + assert_eq!(conf3.net_addresses().unwrap().1.unwrap().port(), 30303); + + // Garbage is error + assert!(conf4.net_addresses().is_err()); + } + + #[test] + fn should_expose_all_servers() { + let (mut conf0, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf0.absorb_cli(raw, user_defaults, fallback).unwrap(); + + conf0.flag_unsafe_expose = true; + + let conf0 = Configuration { + args: conf0 + }; + + assert_eq!(&conf0.network_settings().unwrap().rpc_interface, "0.0.0.0"); + assert_eq!(&conf0.http_config().unwrap().interface, "0.0.0.0"); + assert_eq!(conf0.http_config().unwrap().hosts, None); + assert_eq!(&conf0.ws_config().unwrap().interface, "0.0.0.0"); + assert_eq!(conf0.ws_config().unwrap().hosts, None); + assert_eq!(conf0.ws_config().unwrap().origins, None); + assert_eq!(&conf0.secretstore_config().unwrap().interface, "0.0.0.0"); + assert_eq!(&conf0.secretstore_config().unwrap().http_interface, "0.0.0.0"); + } + + #[test] + fn allow_ips() { + + let (mut all, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + all.absorb_cli(raw, user_defaults, fallback).unwrap(); + + let mut private = all.clone(); + let mut block_custom = all.clone(); + let mut combo = all.clone(); + let mut ipv6_custom_public = all.clone(); + let mut ipv6_custom_private = all.clone(); + + all.arg_allow_ips = "all".to_owned(); + let all = Configuration { + args: all + }; + + private.arg_allow_ips = "private".to_owned(); + let private = Configuration { + args: private + }; + + block_custom.arg_allow_ips = "-10.0.0.0/8".to_owned(); + let block_custom = Configuration { + args: block_custom + }; + + combo.arg_allow_ips = "public 10.0.0.0/8 -1.0.0.0/8".to_owned(); + let combo = Configuration { + args: combo + }; + + ipv6_custom_public.arg_allow_ips = "public fc00::/7".to_owned(); + let ipv6_custom_public = Configuration { + args: ipv6_custom_public + }; + + ipv6_custom_private.arg_allow_ips = "private -fc00::/7".to_owned(); + let ipv6_custom_private = Configuration { + args: ipv6_custom_private + }; + + assert_eq!(all.ip_filter().unwrap(), IpFilter { + predefined: AllowIP::All, + custom_allow: vec![], + custom_block: vec![], + }); + + assert_eq!(private.ip_filter().unwrap(), IpFilter { + predefined: AllowIP::Private, + custom_allow: vec![], + custom_block: vec![], + }); + + assert_eq!(block_custom.ip_filter().unwrap(), IpFilter { + predefined: AllowIP::All, + custom_allow: vec![], + custom_block: vec![IpNetwork::from_str("10.0.0.0/8").unwrap()], + }); + + assert_eq!(combo.ip_filter().unwrap(), IpFilter { + predefined: AllowIP::Public, + custom_allow: vec![IpNetwork::from_str("10.0.0.0/8").unwrap()], + custom_block: vec![IpNetwork::from_str("1.0.0.0/8").unwrap()], + }); + + assert_eq!(ipv6_custom_public.ip_filter().unwrap(), IpFilter { + predefined: AllowIP::Public, + custom_allow: vec![IpNetwork::from_str("fc00::/7").unwrap()], + custom_block: vec![], + }); + + assert_eq!(ipv6_custom_private.ip_filter().unwrap(), IpFilter { + predefined: AllowIP::Private, + custom_allow: vec![], + custom_block: vec![IpNetwork::from_str("fc00::/7").unwrap()], + }); + } + + #[test] + fn should_use_correct_cache_path_if_base_is_set() { + use std::path; + + let (mut std, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + std.absorb_cli(raw, user_defaults, fallback).unwrap(); + + let mut base = std.clone(); + base.arg_base_path = Some("/test".to_owned()); + + let std = Configuration { + args: std + }; + + let base = Configuration { + args: base + }; + + let base_path = ::dir::default_data_path(); + let local_path = ::dir::default_local_path(); + assert_eq!(std.directories().cache, dir::helpers::replace_home_and_local(&base_path, &local_path, ::dir::CACHE_PATH)); + assert_eq!(path::Path::new(&base.directories().cache), path::Path::new("/test/cache")); + } + + #[test] + fn should_respect_only_max_peers_and_default() { + + let (mut conf0, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf0.absorb_cli(raw, user_defaults, fallback).unwrap(); + + conf0.arg_max_peers = Some(50); + + let conf0 = Configuration { + args: conf0 + }; + + match conf0.into_command().unwrap().cmd { + Cmd::Run(c) => { + assert_eq!(c.net_conf.min_peers, 25); + assert_eq!(c.net_conf.max_peers, 50); + }, + _ => panic!("Should be Cmd::Run"), + } + } + + #[test] + fn should_respect_only_max_peers_less_than_default() { + let (mut conf0, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf0.absorb_cli(raw, user_defaults, fallback).unwrap(); + + conf0.arg_max_peers = Some(5); + + let conf0 = Configuration { + args: conf0 + }; + + match conf0.into_command().unwrap().cmd { + Cmd::Run(c) => { + assert_eq!(c.net_conf.min_peers, 5); + assert_eq!(c.net_conf.max_peers, 5); + }, + _ => panic!("Should be Cmd::Run"), + } + } + +} From 34658ecee4d05b348d8079deb4623c7df8725c9b Mon Sep 17 00:00:00 2001 From: Artem Vorotnikov Date: Tue, 2 Jun 2020 07:00:20 +0300 Subject: [PATCH 2/2] Port to Clap 3.0 --- Cargo.lock | 71 +- Cargo.toml | 3 +- ethcore/wasm/run/Cargo.toml | 6 +- ethcore/wasm/run/src/main.rs | 28 +- parity/cli/args.rs | 6 +- parity/cli/globals.rs | 1043 +++++++++++++++++------------ parity/cli/parse_cli.rs | 15 +- parity/cli/subcommands.rs | 140 ++-- parity/cli/tests/test_cli.rs | 2 +- parity/configuration.rs | 1224 ++++++++++++++++++++++++++++++++-- parity/lib.rs | 4 +- parity/test_configuration.rs | 1147 ------------------------------- 12 files changed, 1965 insertions(+), 1724 deletions(-) delete mode 100644 parity/test_configuration.rs diff --git a/Cargo.lock b/Cargo.lock index c2aba399cc3..d6fac85934a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -302,7 +302,7 @@ dependencies = [ "cexpr", "cfg-if", "clang-sys", - "clap", + "clap 2.33.0", "env_logger 0.7.1", "lazy_static", "lazycell", @@ -574,6 +574,36 @@ dependencies = [ "vec_map", ] +[[package]] +name = "clap" +version = "3.0.0-beta.1" +source = "git+https://github.com/clap-rs/clap#f4ace424c4a821765cfac76274967507a74566bb" +dependencies = [ + "atty", + "bitflags", + "clap_derive", + "indexmap", + "lazy_static", + "os_str_bytes", + "strsim 0.10.0", + "termcolor", + "textwrap", + "unicode-width", + "vec_map", +] + +[[package]] +name = "clap_derive" +version = "3.0.0-beta.1" +source = "git+https://github.com/clap-rs/clap#f4ace424c4a821765cfac76274967507a74566bb" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2 1.0.9", + "quote 1.0.3", + "syn 1.0.17", +] + [[package]] name = "cli-signer" version = "1.4.0" @@ -713,7 +743,7 @@ checksum = "1fc755679c12bda8e5523a71e4d654b6bf2e14bd838dfc48cde6559a05caf7d1" dependencies = [ "atty", "cast", - "clap", + "clap 2.33.0", "criterion-plot", "csv", "itertools", @@ -3109,7 +3139,7 @@ dependencies = [ "ansi_term", "atty", "blooms-db", - "clap", + "clap 3.0.0-beta.1", "cli-signer", "client-traits", "common-types", @@ -3176,7 +3206,6 @@ dependencies = [ "serde_json", "snapshot", "spec", - "structopt", "tempfile", "term_size", "textwrap", @@ -3203,6 +3232,12 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063" +[[package]] +name = "os_str_bytes" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06de47b848347d8c4c94219ad8ecd35eb90231704b067e67e6ae2e36ee023510" + [[package]] name = "owning_ref" version = "0.4.1" @@ -3894,8 +3929,8 @@ dependencies = [ name = "pwasm-run-test" version = "0.1.0" dependencies = [ - "clap", - "env_logger 0.5.13", + "clap 3.0.0-beta.1", + "env_logger 0.7.1", "ethereum-types", "ethjson", "rustc-hex 2.1.0", @@ -4826,28 +4861,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" [[package]] -name = "structopt" -version = "0.3.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "863246aaf5ddd0d6928dfeb1a9ca65f505599e4e1b399935ef7e75107516b4ef" -dependencies = [ - "clap", - "lazy_static", - "structopt-derive", -] - -[[package]] -name = "structopt-derive" -version = "0.4.7" +name = "strsim" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d239ca4b13aee7a2142e6795cbd69e457665ff8037aed33b3effdc430d2f927a" -dependencies = [ - "heck", - "proc-macro-error", - "proc-macro2 1.0.9", - "quote 1.0.3", - "syn 1.0.17", -] +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "subtle" diff --git a/Cargo.toml b/Cargo.toml index 19915db40c2..77f7182703b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ authors = [ ansi_term = "0.11" atty = "0.2.8" blooms-db = { path = "util/blooms-db" } -clap = "2" +clap = { git = "https://github.com/clap-rs/clap" } cli-signer= { path = "cli-signer" } client-traits = { path = "ethcore/client-traits" } common-types = { path = "ethcore/types" } @@ -75,7 +75,6 @@ serde_derive = "1.0" serde_json = "1.0" snapshot = { path = "ethcore/snapshot" } spec = { path = "ethcore/spec" } -structopt = "~0.3" term_size = "0.3" textwrap = "0.11.0" toml = "0.5.6" diff --git a/ethcore/wasm/run/Cargo.toml b/ethcore/wasm/run/Cargo.toml index 2dd2bae030f..008036f6714 100644 --- a/ethcore/wasm/run/Cargo.toml +++ b/ethcore/wasm/run/Cargo.toml @@ -8,12 +8,12 @@ authors = ["Parity Technologies "] serde = "1" serde_json = "1" serde_derive = "1" -ethereum-types = "0.9.0" +ethereum-types = "0.9" ethjson = { path = "../../../json" } vm = { path = "../../vm" } wasm = { path = "../" } -clap = "2.24" -env_logger = "0.5" +clap = { git = "https://github.com/clap-rs/clap" } +env_logger = "0.7" rustc-hex = "2.1.0" [features] diff --git a/ethcore/wasm/run/src/main.rs b/ethcore/wasm/run/src/main.rs index a8a48bcca8a..6742427edad 100644 --- a/ethcore/wasm/run/src/main.rs +++ b/ethcore/wasm/run/src/main.rs @@ -29,24 +29,30 @@ mod fixture; mod runner; use fixture::Fixture; -use clap::{App, Arg}; +use clap::Clap; use std::fs; +#[derive(Clap)] +#[clap( + name = "pwasm-run-test", +)] +struct Options { + #[clap( + required = true, + name = "target", + min_values = 1, + about = "JSON fixture", + )] + pub target: Vec +} + fn main() { ::env_logger::init(); - let matches = App::new("pwasm-run-test") - .arg(Arg::with_name("target") - .index(1) - .required(true) - .multiple(true) - .help("JSON fixture")) - .get_matches(); - let mut exit_code = 0; - for target in matches.values_of("target").expect("No target parameter") { - let mut f = fs::File::open(target).expect("Failed to open file"); + for target in Options::parse().target { + let mut f = fs::File::open(&target).expect("Failed to open file"); let fixtures: Vec = serde_json::from_reader(&mut f).expect("Failed to deserialize json"); for fixture in fixtures.into_iter() { diff --git a/parity/cli/args.rs b/parity/cli/args.rs index 1401c034509..c1f140e08a6 100644 --- a/parity/cli/args.rs +++ b/parity/cli/args.rs @@ -1,9 +1,9 @@ +use clap::Clap; use cli::config::get_config; use cli::globals::{Globals, IPCOptions}; use cli::parse_cli::*; use cli::subcommands::*; use std::fs; -use structopt::StructOpt; #[derive(Debug, PartialEq)] pub enum ArgsError { @@ -216,8 +216,6 @@ pub struct Args { pub arg_max_round_blocks_to_import: usize, pub flag_can_restart: bool, pub flag_no_color: bool, - // NOTE: This is auto handled by structopt - // pub flag_version: bool, pub flag_no_config: bool, pub arg_logging: Option, pub arg_log_file: Option, @@ -247,7 +245,7 @@ impl Args { pub fn parse() -> Result { let mut args: Args = Default::default(); - let mut raw_input = ArgsInput::from_args(); + let mut raw_input = ArgsInput::parse(); Args::save_current_config(&mut raw_input.globals)?; diff --git a/parity/cli/globals.rs b/parity/cli/globals.rs index 39c7d4440f0..6aa60330ac1 100644 --- a/parity/cli/globals.rs +++ b/parity/cli/globals.rs @@ -1,173 +1,213 @@ use serde_derive::{Deserialize, Serialize}; -use structopt::StructOpt; - -#[derive(PartialEq, Default, StructOpt, Serialize, Deserialize, Debug, Clone)] +use clap::Clap; + +const OPERATING: &str = "Operating Options"; +const CONVENIENCE: &str = "Convenience Options"; +const ACCOUNT: &str = "Account Options"; +const PRIVATE_TRANSACTIONS: &str = "Private Transactions Options"; +const UI: &str = "UI Options"; +const NETWORKING: &str = "Nethworking Options"; +const IPC: &str = "IPC Options"; +const HTTP_JSON_RPC: &str = "HTTP/JSONRPC Options"; +const LIGHT_CLIENT: &str = "Light Client Options"; +const WEBSOCKETS: &str = "WebSockets Options"; +const SECRET_STORE: &str = "Secret Store Options"; +const SEALING_MINING: &str = "Sealing/Mining Options"; +const INTERNAL: &str = "Internal Options"; +const MISCELLANEOUS: &str = "Miscellaneous Options"; +const FOOTPRINT: &str = "Footprint Options"; +const IMPORT_EXPORT: &str = "Import/Export Options"; +const SNAPSHOT: &str = "Snapshot Options"; +const LEGACY: &str = "Legacy Options"; + +#[derive(PartialEq, Default, Clap, Serialize, Deserialize, Debug, Clone)] pub struct Globals { - #[structopt(flatten)] + #[clap(flatten)] pub operating: OperatingOptions, - #[structopt(flatten)] + #[clap(flatten)] pub convenience: ConvenienceOptions, - #[structopt(flatten)] + #[clap(flatten)] pub account: AccountOptions, - #[structopt(flatten)] + #[clap(flatten)] pub private_transactions: PrivateTransactions, - #[structopt(flatten)] + #[clap(flatten)] pub ui_options: UIOptons, - #[structopt(flatten)] + #[clap(flatten)] pub networking: NetworkingOptions, - #[structopt(flatten)] + #[clap(flatten)] pub ipc: IPCOptions, - #[structopt(flatten)] + #[clap(flatten)] pub http_json_rpc: HttpJsonRpcOptions, - #[structopt(flatten)] + #[clap(flatten)] pub light_client: LightClientOptions, - #[structopt(flatten)] + #[clap(flatten)] pub websockets: WebsocketsOptions, - #[structopt(flatten)] + #[clap(flatten)] pub secret_store: SecretStoreOptions, - #[structopt(flatten)] + #[clap(flatten)] pub sealing_mining: SealingMiningOptions, - #[structopt(flatten)] + #[clap(flatten)] pub internal: InternalOptions, - #[structopt(flatten)] + #[clap(flatten)] pub miscellaneous: MiscellaneousOptions, - #[structopt(flatten)] + #[clap(flatten)] pub footprint: FootPrintOptions, - #[structopt(flatten)] + #[clap(flatten)] pub import_export: ImportExportOptions, - #[structopt(flatten)] + #[clap(flatten)] pub snapshot: SnapshotOptions, - #[structopt(flatten)] + #[clap(flatten)] pub legacy: LegacyOptions, } -#[derive(StructOpt, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] +#[derive(Clap, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] pub struct OperatingOptions { - #[structopt( + #[clap( long = "no-download", - help = "Normally new releases will be downloaded ready for updating. This disables it. Not recommended." + about = "Normally new releases will be downloaded ready for updating. This disables it. Not recommended.", + help_heading = Some(OPERATING), )] pub no_download: bool, - #[structopt( + #[clap( long = "no-consensus", - help = "Force the binary to run even if there are known issues regarding consensus. Not recommended." + about = "Force the binary to run even if there are known issues regarding consensus. Not recommended.", + help_heading = Some(OPERATING), )] pub no_consensus: bool, - #[structopt( + #[clap( long, - help = "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." + about = "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.", + help_heading = Some(OPERATING), )] pub light: bool, - #[structopt( + #[clap( long = "no-hardcoded-sync", - help = "By default, if there is no existing database the light client will automatically jump to a block hardcoded in the chain's specifications. This disables this feature." + about = "By default, if there is no existing database the light client will automatically jump to a block hardcoded in the chain's specifications. This disables this feature.", + help_heading = Some(OPERATING), )] pub no_hardcoded_sync: bool, - #[structopt( + #[clap( long = "force-direct", - help = "Run the originally installed version of Parity, ignoring any updates that have since been installed." + about = "Run the originally installed version of Parity, ignoring any updates that have since been installed.", + help_heading = Some(OPERATING), )] pub force_direct: bool, - #[structopt( + #[clap( name = "MODE", long, - help = "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 JSON-RPC is active; offline - Parity doesn't sync." + about = "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 JSON-RPC is active; offline - Parity doesn't sync.", + help_heading = Some(OPERATING), )] pub mode: Option, - #[structopt( + #[clap( long = "mode-timeout", name = "TIMEOUT_IN_SECS", - help = "Specify the number of seconds before inactivity timeout occurs when mode is dark or passive" + about = "Specify the number of seconds before inactivity timeout occurs when mode is dark or passive", + help_heading = Some(OPERATING), )] pub mode_timeout: Option, - #[structopt( + #[clap( long = "mode-alarm", name = "ALARM_IN_SECS", - help = "Specify the number of seconds before auto sleep reawake timeout occurs when mode is passive" + about = "Specify the number of seconds before auto sleep reawake timeout occurs when mode is passive", + help_heading = Some(OPERATING), )] pub mode_alarm: Option, - #[structopt( + #[clap( long = "auto-update", name = "SET", - help = "Set a releases set to automatically update and install. SET can be one of: all - All updates in the our release track; critical - Only consensus/security updates; none - No updates will be auto-installed." + about = "Set a releases set to automatically update and install. SET can be one of: all - All updates in the our release track; critical - Only consensus/security updates; none - No updates will be auto-installed.", + help_heading = Some(OPERATING), )] pub auto_update: Option, - #[structopt( + #[clap( long = "auto-update-delay", name = "DELAY_NUM", - help = "Specify the maximum number of blocks used for randomly delaying updates." + about = "Specify the maximum number of blocks used for randomly delaying updates.", + help_heading = Some(OPERATING), )] pub auto_update_delay: Option, - #[structopt( + #[clap( long = "auto-update-check-frequency", name = "FREQUENCY_NUM", - help = "Specify the number of blocks between each auto-update check." + about = "Specify the number of blocks between each auto-update check.", + help_heading = Some(OPERATING), )] pub auto_update_check_frequency: Option, - #[structopt( + #[clap( long = "release-track", name = "TRACK", - help = "Set which release track we should use for updates. TRACK can be one of: stable - Stable releases; nightly - Nightly releases (unstable); testing - Testing releases (do not use); current - Whatever track this executable was released on." + about = "Set which release track we should use for updates. TRACK can be one of: stable - Stable releases; nightly - Nightly releases (unstable); testing - Testing releases (do not use); current - Whatever track this executable was released on.", + help_heading = Some(OPERATING), )] pub release_track: Option, - #[structopt( + #[clap( long, name = "CHAIN", - help = "Specify the blockchain type. CHAIN may be either a JSON chain specification file or ethereum, classic, classic-no-phoenix, poacore, xdai, volta, ewc, musicoin, ellaism, mix, callisto, ethercore, mordor, ropsten, kovan, rinkeby, goerli, kotti, poasokol, testnet, evantestcore, evancore or dev." + about = "Specify the blockchain type. CHAIN may be either a JSON chain specification file or ethereum, classic, classic-no-phoenix, poacore, xdai, volta, ewc, musicoin, ellaism, mix, callisto, ethercore, mordor, ropsten, kovan, rinkeby, goerli, kotti, poasokol, testnet, evantestcore, evancore or dev.", + help_heading = Some(OPERATING), )] pub chain: Option, - #[structopt( + #[clap( long = "keys-path", name = "KEYS_PATH", - help = "Specify the path for JSON key files to be found" + about = "Specify the path for JSON key files to be found", + help_heading = Some(OPERATING), )] pub keys_path: Option, - #[structopt(name = "NAME", long, help = "Specify your node's name.")] + #[clap( + name = "NAME", + long, + about = "Specify your node's name.", + help_heading = Some(OPERATING), + )] pub identity: Option, - #[structopt( + #[clap( short = "d", long = "base-path", name = "BASE_PATH", - help = "Specify the base data storage path." + about = "Specify the base data storage path.", + help_heading = Some(OPERATING), )] pub base_path: Option, - #[structopt( - name = "DB_PATH", + #[clap( long = "db-path", - help = "Specify the database directory path" + name = "DB_PATH", + about = "Specify the database directory path", + help_heading = Some(OPERATING), )] pub db_path: Option, @@ -180,286 +220,339 @@ pub struct OperatingOptions { pub sync_until: Option, } -#[derive(StructOpt, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] +#[derive(Clap, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] pub struct ConvenienceOptions { - #[structopt( + #[clap( long = "unsafe-expose", - help = "All servers will listen on external interfaces and will be remotely accessible. It's equivalent with setting the following: --[ws,jsonrpc,secretstore,stratum,dapps,secretstore-http]-interface=all --*-hosts=all This option is UNSAFE and should be used with great care!" + about = "All servers will listen on external interfaces and will be remotely accessible. It's equivalent with setting the following: --[ws,jsonrpc,secretstore,stratum,dapps,secretstore-http]-interface=all --*-hosts=all This option is UNSAFE and should be used with great care!", + help_heading = Some(CONVENIENCE), )] pub unsafe_expose: bool, - #[structopt( + #[clap( short, long, name = "CONFIG", - help = "Specify a configuration. CONFIG may be either a configuration file or a preset: dev, insecure, dev-insecure, mining, or non-standard-ports." + about = "Specify a configuration. CONFIG may be either a configuration file or a preset: dev, insecure, dev-insecure, mining, or non-standard-ports.", + help_heading = Some(CONVENIENCE), )] pub config: Option, - #[structopt( + #[clap( long = "config-generate", name = "PATH_TO_GENERATE_CONFIG_IN", - help = "Save the current flags and their values into a configuration for future use" + about = "Save the current flags and their values into a configuration for future use", + help_heading = Some(CONVENIENCE), )] pub config_generate: Option, - #[structopt( + #[clap( long = "ports-shift", name = "SHIFT", - help = "Add SHIFT to all port numbers Parity is listening on. Includes network port and all servers (HTTP JSON-RPC, WebSockets JSON-RPC, SecretStore)." + about = "Add SHIFT to all port numbers Parity is listening on. Includes network port and all servers (HTTP JSON-RPC, WebSockets JSON-RPC, SecretStore).", + help_heading = Some(CONVENIENCE), )] pub ports_shift: Option, } -#[derive(StructOpt, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] +#[derive(Clap, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] pub struct AccountOptions { - #[structopt( + #[clap( long = "fast-unlock", name = "FAST_UNLOCK_BOOL", - help = "Use drastically faster unlocking mode. This setting causes raw secrets to be stored unprotected in memory, so use with care." + about = "Use drastically faster unlocking mode. This setting causes raw secrets to be stored unprotected in memory, so use with care.", + help_heading = Some(ACCOUNT), )] pub fast_unlock: bool, - #[structopt( + #[clap( long = "keys-iterations", - help = "Specify the number of iterations to use when deriving key from the password (bigger is more secure)", - name = "NUM" + name = "NUM_KEYS_INTERATIONS", + about = "Specify the number of iterations to use when deriving key from the password (bigger is more secure)", + help_heading = Some(ACCOUNT), )] pub keys_iterations: Option, - #[structopt( + #[clap( long = "accounts-refresh", - help = "Specify the cache time of accounts read from disk. If you manage thousands of accounts set this to 0 to disable refresh.", - name = "TIME" + name = "TIME", + about = "Specify the cache time of accounts read from disk. If you manage thousands of accounts set this to 0 to disable refresh.", + help_heading = Some(ACCOUNT), )] pub accounts_refresh: Option, - #[structopt( + #[clap( long, - help = "Unlock UNLOCK_ACCOUNTS for the duration of the execution. UNLOCK_ACCOUNTS is a comma-delimited list of addresses.", - name = "UNLOCK_ACCOUNTS" + name = "UNLOCK_ACCOUNTS", + about = "Unlock UNLOCK_ACCOUNTS for the duration of the execution. UNLOCK_ACCOUNTS is a comma-delimited list of addresses.", + help_heading = Some(ACCOUNT), )] pub unlock: Option, - #[structopt( + #[clap( long = "enable-signing-queue", name = "BOOLEAN", - help = "Enables the signing queue for external transaction signing either via CLI or personal_unlockAccount, turned off by default." + about = "Enables the signing queue for external transaction signing either via CLI or personal_unlockAccount, turned off by default.", + help_heading = Some(ACCOUNT), )] pub enable_signing_queue: bool, - #[structopt( + #[clap( long, name = "FILE", - help = "Provide a file containing a password for unlocking an account. Leading and trailing whitespace is trimmed." + about = "Provide a file containing a password for unlocking an account. Leading and trailing whitespace is trimmed.", + help_heading = Some(ACCOUNT), )] pub password: Vec, // FIXME: Why is this a Vec? } -#[derive(StructOpt, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] +#[derive(Clap, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] pub struct PrivateTransactions { - #[structopt(long = "private-tx-enabled", help = "Enable private transactions.")] + #[clap( + long = "private-tx-enabled", + about = "Enable private transactions.", + help_heading = Some(PRIVATE_TRANSACTIONS), + )] pub private_enabled: bool, - #[structopt( + #[clap( long = "private-state-offchain", - help = "Store private state offchain (in the local DB)." + about = "Store private state offchain (in the local DB).", + help_heading = Some(PRIVATE_TRANSACTIONS), )] pub private_state_offchain: bool, - #[structopt( + #[clap( long = "private-signer", name = "ACCOUNT", - help = "Specify the account for signing public transaction created upon verified private transaction." + about = "Specify the account for signing public transaction created upon verified private transaction.", + help_heading = Some(PRIVATE_TRANSACTIONS), )] pub private_signer: Option, - #[structopt( + #[clap( long = "private-validators", name = "ACCOUNTS", - help = "Specify the accounts for validating private transactions. ACCOUNTS is a comma-delimited list of addresses." + about = "Specify the accounts for validating private transactions. ACCOUNTS is a comma-delimited list of addresses.", + help_heading = Some(PRIVATE_TRANSACTIONS), )] pub private_validators: Option, - #[structopt( + #[clap( long = "private-account", name = "PRIVATE_ACCOUNT", - help = "Specify the account for signing requests to secret store." + about = "Specify the account for signing requests to secret store.", + help_heading = Some(PRIVATE_TRANSACTIONS), )] pub private_account: Option, - #[structopt( + #[clap( long = "private-sstore-url", name = "URL", - help = "Specify secret store URL used for encrypting private transactions." + about = "Specify secret store URL used for encrypting private transactions.", + help_heading = Some(PRIVATE_TRANSACTIONS), )] pub private_sstore_url: Option, - #[structopt( + #[clap( long = "private-sstore-threshold", name = "THRESHOLD_NUM", - help = "Specify secret store threshold used for encrypting private transactions." + about = "Specify secret store threshold used for encrypting private transactions.", + help_heading = Some(PRIVATE_TRANSACTIONS), )] pub private_sstore_threshold: Option, - #[structopt( + #[clap( long = "private-passwords", name = "PASS_FILE", - help = "Provide a file containing passwords for unlocking accounts (signer, private account, validators)." + about = "Provide a file containing passwords for unlocking accounts (signer, private account, validators).", + help_heading = Some(PRIVATE_TRANSACTIONS), )] pub private_passwords: Option, } -#[derive(StructOpt, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] +#[derive(Clap, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] pub struct UIOptons { - #[structopt( + #[clap( long = "ui-path", - help = "Specify directory where Trusted UIs tokens should be stored." + about = "Specify directory where Trusted UIs tokens should be stored.", + help_heading = Some(UI), )] pub ui_path: Option, } -#[derive(StructOpt, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] +#[derive(Clap, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] pub struct NetworkingOptions { - #[structopt( + #[clap( long = "no-warp", - help = "Disable syncing from the snapshot over the network." + about = "Disable syncing from the snapshot over the network.", + help_heading = Some(NETWORKING), )] pub no_warp: bool, - #[structopt(long = "no-discovery", help = "Disable new peer discovery.")] + #[clap( + long = "no-discovery", + about = "Disable new peer discovery.", + help_heading = Some(NETWORKING), + )] pub no_discovery: bool, - #[structopt(long = "reserved-only", help = "Connect only to reserved nodes.")] + #[clap( + long = "reserved-only", + about = "Connect only to reserved nodes.", + help_heading = Some(NETWORKING), + )] pub reserved_only: bool, - #[structopt( + #[clap( long = "no-ancient-blocks", - help = "Disable downloading old blocks after snapshot restoration or warp sync. Not recommended." + about = "Disable downloading old blocks after snapshot restoration or warp sync. Not recommended.", + help_heading = Some(NETWORKING), )] pub no_ancient_blocks: bool, - #[structopt(long = "no-serve-light", help = "Disable serving of light peers.")] + #[clap( + long = "no-serve-light", + about = "Disable serving of light peers.", + help_heading = Some(NETWORKING), + )] pub no_serve_light: bool, - #[structopt( + #[clap( long = "warp-barrier", name = "WARP_BARRIER_NUM", - help = "When warp enabled never attempt regular sync before warping to block WARP_BARRIER_NUM." + about = "When warp enabled never attempt regular sync before warping to block WARP_BARRIER_NUM.", + help_heading = Some(NETWORKING), )] pub warp_barrier: Option, - #[structopt( + #[clap( long, name = "PORT", - help = "Override the port on which the node should listen." + about = "Override the port on which the node should listen.", + help_heading = Some(NETWORKING), )] pub port: Option, - #[structopt( + #[clap( long, name = "IP", - help = "Network interfaces. Valid values are 'all', 'local' or the ip of the interface you want parity to listen to." + about = "Network interfaces. Valid values are 'all', 'local' or the ip of the interface you want parity to listen to.", + help_heading = Some(NETWORKING), )] pub interface: Option, - #[structopt( + #[clap( long = "min-peers", name = "MIN_NUM", - help = "Try to maintain at least MIN_NUM peers." + about = "Try to maintain at least MIN_NUM peers.", + help_heading = Some(NETWORKING), )] pub min_peers: Option, - #[structopt( + #[clap( long = "max-peers", name = "MAX_NUM", - help = "Try to maintain at least MAX_NUM peers." + about = "Try to maintain at least MAX_NUM peers.", + help_heading = Some(NETWORKING), )] pub max_peers: Option, - #[structopt( + #[clap( long = "snapshot-peers", name = "SNAPSHOT_NUM", - help = "Allow additional SNAPSHOT_NUM peers for a snapshot sync." + about = "Allow additional SNAPSHOT_NUM peers for a snapshot sync.", + help_heading = Some(NETWORKING), )] pub snapshot_peers: Option, - #[structopt( + #[clap( long, - help = "Specify method to use for determining public address. Must be one of: any, none, upnp, extip:.", - name = "METHOD" + name = "METHOD", + about = "Specify method to use for determining public address. Must be one of: any, none, upnp, extip:.", + help_heading = Some(NETWORKING), )] pub nat: Option, - #[structopt( + #[clap( long = "allow-ips", - help = "Filter outbound connections. Must 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.", - name = "FILTER" + name = "FILTER", + about = "Filter outbound connections. Must 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.", + help_heading = Some(NETWORKING), )] pub allow_ips: Option, - #[structopt( + #[clap( long = "max-pending-peers", - help = "Allow up to PENDING_NUM pending connections.", - name = "PENDING_NUM" + name = "PENDING_NUM", + about = "Allow up to PENDING_NUM pending connections.", + help_heading = Some(NETWORKING), )] pub max_pending_peers: Option, - #[structopt( + #[clap( long = "network-id", - help = "Override the network identifier from the chain we are on.", - name = "INDEX" + name = "INDEX", + about = "Override the network identifier from the chain we are on.", + help_heading = Some(NETWORKING), )] pub network_id: Option, - #[structopt( + #[clap( long, name = "BOOTNODES", - help = "Override the bootnodes from our chain. NODES should be comma-delimited enodes." + about = "Override the bootnodes from our chain. NODES should be comma-delimited enodes.", + help_heading = Some(NETWORKING), )] pub bootnodes: Option, - #[structopt( + #[clap( long = "node-key", name = "NODE_KEY", - help = "Specify node secret key, either as 64-character hex string or input to SHA3 operation." + about = "Specify node secret key, either as 64-character hex string or input to SHA3 operation.", + help_heading = Some(NETWORKING), )] pub node_key: Option, - #[structopt( + #[clap( long = "reserved-peers", name = "RESERVED_PEERS_FILE", - help = "Provide a file containing enodes, one per line. These nodes will always have a reserved slot on top of the normal maximum peers." + about = "Provide a file containing enodes, one per line. These nodes will always have a reserved slot on top of the normal maximum peers.", + help_heading = Some(NETWORKING), )] pub reserved_peers: Option, } -#[derive(StructOpt, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] +#[derive(Clap, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] pub struct IPCOptions { - #[structopt( - help = "Provide a file containing enodes, one per line. These nodes will always have a reserved slot on top of the normal maximum peers.", - long = "no-ipc" + #[clap( + long = "no-ipc", + about = "Provide a file containing enodes, one per line. These nodes will always have a reserved slot on top of the normal maximum peers.", + help_heading = Some(IPC), )] pub no_ipc: bool, - #[structopt( - help = "Provide a file containing enodes, one per line. These nodes will always have a reserved slot on top of the normal maximum peers.", + #[clap( long = "ipc-path", - name = "IPC_PATH" + name = "IPC_PATH", + about = "Provide a file containing enodes, one per line. These nodes will always have a reserved slot on top of the normal maximum peers.", + help_heading = Some(IPC), )] pub ipc_path: Option, - #[structopt( + #[clap( long = "ipc-chmod", name = "IPC_CHMOD_NUM", - help = "Specify octal value for ipc socket permissions (unix/bsd only)" + about = "Specify octal value for ipc socket permissions (unix/bsd only)", + help_heading = Some(IPC), )] pub ipc_chmod: Option, - #[structopt( + #[clap( long = "ipc-apis", name = "IPC_APIS", - help = "Specify custom API set available via JSON-RPC over IPC using a comma-delimited list of API names. Possible names are: all, safe, web3, net, eth, pubsub, personal, signer, parity, parity_pubsub, parity_accounts, parity_set, traces, rpc, secretstore. You can also disable a specific API by putting '-' in the front, example: all,-personal. 'safe' enables the following APIs: web3, net, eth, pubsub, parity, parity_pubsub, traces, rpc" + about = "Specify custom API set available via JSON-RPC over IPC using a comma-delimited list of API names. Possible names are: all, safe, web3, net, eth, pubsub, personal, signer, parity, parity_pubsub, parity_accounts, parity_set, traces, rpc, secretstore. You can also disable a specific API by putting '-' in the front, example: all,-personal. 'safe' enables the following APIs: web3, net, eth, pubsub, parity, parity_pubsub, traces, rpc", + help_heading = Some(IPC), )] pub ipc_apis: Option, } @@ -474,704 +567,830 @@ impl IPCOptions { } } -#[derive(StructOpt, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] +#[derive(Clap, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] pub struct HttpJsonRpcOptions { - #[structopt( + #[clap( long = "json-rpc-allow-missing-blocks", - help = "RPC calls will return 'null' instead of an error if ancient block sync is still in progress and the block information requested could not be found" + about = "RPC calls will return 'null' instead of an error if ancient block sync is still in progress and the block information requested could not be found", + help_heading = Some(HTTP_JSON_RPC), )] pub jsonrpc_allow_missing_blocks: bool, - #[structopt(long = "no-jsonrpc", help = "Disable the HTTP JSON-RPC API server.")] + #[clap( + long = "no-jsonrpc", + about = "Disable the HTTP JSON-RPC API server.", + help_heading = Some(HTTP_JSON_RPC), + )] pub no_jsonrpc: bool, - #[structopt( + #[clap( long = "jsonrpc-no-keep-alive", - help = "Disable HTTP/1.1 keep alive header. Disabling keep alive will prevent re-using the same TCP connection to fire multiple requests, recommended when using one request per connection." + about = "Disable HTTP/1.1 keep alive header. Disabling keep alive will prevent re-using the same TCP connection to fire multiple requests, recommended when using one request per connection.", + help_heading = Some(HTTP_JSON_RPC), )] pub jsonrpc_no_keep_alive: bool, - #[structopt( + #[clap( long = "jsonrpc-experimental", - help = "Enable experimental RPCs. Enable to have access to methods from unfinalised EIPs in all namespaces" + about = "Enable experimental RPCs. Enable to have access to methods from unfinalised EIPs in all namespaces", + help_heading = Some(HTTP_JSON_RPC), )] pub jsonrpc_experimental: bool, - #[structopt( + #[clap( long = "jsonrpc-port", name = "JSONRPC_PORT", - help = "Specify the port portion of the HTTP JSON-RPC API server." + about = "Specify the port portion of the HTTP JSON-RPC API server.", + help_heading = Some(HTTP_JSON_RPC), )] pub jsonrpc_port: Option, - #[structopt( + #[clap( long = "jsonrpc-interface", name = "JSONRPC_IP", - help = "Specify the hostname portion of the HTTP JSON-RPC API server, JSONRPC_IP should be an interface's IP address, or all (all interfaces) or local." + about = "Specify the hostname portion of the HTTP JSON-RPC API server, JSONRPC_IP should be an interface's IP address, or all (all interfaces) or local.", + help_heading = Some(HTTP_JSON_RPC), )] pub jsonrpc_interface: Option, - #[structopt( + #[clap( long = "jsonrpc-apis", name = "JSONRPC_APIS", - help = "Specify the APIs available through the HTTP JSON-RPC interface using a comma-delimited list of API names. Possible names are: all, safe, debug, web3, net, eth, pubsub, personal, signer, parity, parity_pubsub, parity_accounts, parity_set, traces, rpc, secretstore. You can also disable a specific API by putting '-' in the front, example: all,-personal. 'safe' enables the following APIs: web3, net, eth, pubsub, parity, parity_pubsub, traces, rpc" + about = "Specify the APIs available through the HTTP JSON-RPC interface using a comma-delimited list of API names. Possible names are: all, safe, debug, web3, net, eth, pubsub, personal, signer, parity, parity_pubsub, parity_accounts, parity_set, traces, rpc, secretstore. You can also disable a specific API by putting '-' in the front, example: all,-personal. 'safe' enables the following APIs: web3, net, eth, pubsub, parity, parity_pubsub, traces, rpc", + help_heading = Some(HTTP_JSON_RPC), )] pub jsonrpc_apis: Option, - #[structopt( + #[clap( long = "jsonrpc-hosts", name = "JSONRPC_HOSTS", - help = "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\",." + about = "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\",.", + help_heading = Some(HTTP_JSON_RPC), )] pub jsonrpc_hosts: Option, - #[structopt( + #[clap( long = "jsonrpc-server-threads", name = "JSONRPC_SERVER_THREADS", - help = "Enables multiple threads handling incoming connections for HTTP JSON-RPC server." + about = "Enables multiple threads handling incoming connections for HTTP JSON-RPC server.", + help_heading = Some(HTTP_JSON_RPC), )] pub jsonrpc_server_threads: Option, - #[structopt( + #[clap( name = "JSONRPC_CORS_URL", long = "jsonrpc-cors", - help = "Specify CORS header for HTTP JSON-RPC API responses. Special options: \"all\", \"none\"." + about = "Specify CORS header for HTTP JSON-RPC API responses. Special options: \"all\", \"none\".", + help_heading = Some(HTTP_JSON_RPC), )] pub jsonrpc_cors: Option, - #[structopt( + #[clap( long = "jsonrpc-max-payload", name = "JSONRPC_MAX_MB", - help = "Specify maximum size for HTTP JSON-RPC requests in megabytes." + about = "Specify maximum size for HTTP JSON-RPC requests in megabytes.", + help_heading = Some(HTTP_JSON_RPC), )] pub jsonrpc_max_payload: Option, - #[structopt( + #[clap( name = "POLL_LIFETIME_SECS", long = "poll-lifetime", - help = "Set the RPC filter lifetime to S seconds. The filter has to be polled at least every S seconds , otherwise it is removed." + about = "Set the RPC filter lifetime to S seconds. The filter has to be polled at least every S seconds , otherwise it is removed.", + help_heading = Some(HTTP_JSON_RPC), )] pub poll_lifetime: Option, } -#[derive(StructOpt, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] +#[derive(Clap, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] pub struct LightClientOptions { - #[structopt( + #[clap( long = "on-demand-time-window", - help = "Specify the maximum time to wait for a successful response", - name = "RESPONSE_SECS" + about = "Specify the maximum time to wait for a successful response", + name = "RESPONSE_SECS", + help_heading = Some(LIGHT_CLIENT), )] pub on_demand_response_time_window: Option, - #[structopt( + #[clap( long = "on-demand-start-backoff", name = "BACKOFF_START_SECS", - help = "Specify light client initial backoff time for a request" + about = "Specify light client initial backoff time for a request", + help_heading = Some(LIGHT_CLIENT), )] pub on_demand_request_backoff_start: Option, - #[structopt( + #[clap( long = "on-demand-end-backoff", name = "BACKOFF_END_SECS", - help = "Specify light client maximam backoff time for a request" + about = "Specify light client maximam backoff time for a request", + help_heading = Some(LIGHT_CLIENT), )] pub on_demand_request_backoff_max: Option, - #[structopt( + #[clap( long = "on-demand-max-backoff-rounds", name = "BACKOFF_MAX_ROUNDS_TIMES", - help = "Specify light client maximam number of backoff iterations for a request" + about = "Specify light client maximam number of backoff iterations for a request", + help_heading = Some(LIGHT_CLIENT), )] pub on_demand_request_backoff_rounds_max: Option, - #[structopt( + #[clap( long = "on-demand-consecutive-failures", name = "MAX_CONSECUTIVE_FAILURE_TIMES", - help = "Specify light client the number of failures for a request until it gets exponentially backed off" + about = "Specify light client the number of failures for a request until it gets exponentially backed off", + help_heading = Some(LIGHT_CLIENT), )] pub on_demand_request_consecutive_failures: Option, } -#[derive(StructOpt, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] +#[derive(Clap, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] pub struct WebsocketsOptions { - #[structopt(help = "Disable the WebSockets JSON-RPC server.", long = "no-ws")] + #[clap( + about = "Disable the WebSockets JSON-RPC server.", + long = "no-ws", + help_heading = Some(WEBSOCKETS), + )] pub no_ws: bool, - #[structopt( + #[clap( long = "ws-port", name = "WS_PORT", - help = "Specify the port portion of the WebSockets JSON-RPC server." + about = "Specify the port portion of the WebSockets JSON-RPC server.", + help_heading = Some(WEBSOCKETS), )] pub ws_port: Option, - #[structopt( + #[clap( long = "ws-interface", name = "WS_INTERFACE_IP", - help = "Specify the hostname portion of the WebSockets JSON-RPC server, IP should be an interface's IP address, or all (all interfaces) or local." + about = "Specify the hostname portion of the WebSockets JSON-RPC server, IP should be an interface's IP address, or all (all interfaces) or local.", + help_heading = Some(WEBSOCKETS), )] pub ws_interface: Option, - #[structopt( - help = "Specify the JSON-RPC APIs available through the WebSockets interface using a comma-delimited list of API names. Possible names are: all, safe, web3, net, eth, pubsub, personal, signer, parity, parity_pubsub, parity_accounts, parity_set, traces, rpc, secretstore. You can also disable a specific API by putting '-' in the front, example: all,-personal. 'safe' enables the following APIs: web3, net, eth, pubsub, parity, parity_pubsub, traces, rpc", + #[clap( long = "ws-apis", - name = "WS_APIS" + name = "WS_APIS", + about = "Specify the JSON-RPC APIs available through the WebSockets interface using a comma-delimited list of API names. Possible names are: all, safe, web3, net, eth, pubsub, personal, signer, parity, parity_pubsub, parity_accounts, parity_set, traces, rpc, secretstore. You can also disable a specific API by putting '-' in the front, example: all,-personal. 'safe' enables the following APIs: web3, net, eth, pubsub, parity, parity_pubsub, traces, rpc", + help_heading = Some(WEBSOCKETS), )] pub ws_apis: Option, - #[structopt( - help = "Specify Origin header values allowed to connect. Special options: \"all\", \"none\".", + #[clap( long = "ws-origins", - name = "WS_ORIGINS_URL" + name = "WS_ORIGINS_URL", + about = "Specify Origin header values allowed to connect. Special options: \"all\", \"none\".", + help_heading = Some(WEBSOCKETS), )] pub ws_origins: Option, - #[structopt( - help = "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\".", + #[clap( long = "ws-hosts", - name = "WS_HOSTS" + name = "WS_HOSTS", + about = "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\".", + help_heading = Some(WEBSOCKETS), )] pub ws_hosts: Option, - #[structopt( - help = "Maximum number of allowed concurrent WebSockets JSON-RPC connections.", + #[clap( long = "ws-connections", - name = "WS_MAX_CONN" + name = "WS_MAX_CONN", + about = "Maximum number of allowed concurrent WebSockets JSON-RPC connections.", + help_heading = Some(WEBSOCKETS), )] pub ws_max_connections: Option, } -#[derive(StructOpt, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] +#[derive(Clap, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] pub struct SecretStoreOptions { - #[structopt(help = "Disable Secret Store functionality.", long = "no-secretstore")] + #[clap( + long = "no-secretstore", + about = "Disable Secret Store functionality.", + help_heading = Some(SECRET_STORE), + )] pub no_secretstore: bool, - #[structopt(help = "Disable Secret Store HTTP API.", long = "no-secretstore-http")] + #[clap( + long = "no-secretstore-http", + about = "Disable Secret Store HTTP API.", + help_heading = Some(SECRET_STORE), + )] pub no_secretstore_http: bool, - #[structopt( - help = "Do not run servers set change session automatically when servers set changes. This option has no effect when servers set is read from configuration file.", - long = "no-secretstore-auto-migrate" + #[clap( + long = "no-secretstore-auto-migrate", + about = "Do not run servers set change session automatically when servers set changes. This option has no effect when servers set is read from configuration file.", + help_heading = Some(SECRET_STORE), )] pub no_secretstore_auto_migrate: bool, - #[structopt( + #[clap( + long = "secretstore-http-cors", name = "HTTP_CORS_URLS", - help = "Specify CORS header for Secret Store HTTP API responses. Special options: \"all\", \"none\".", - long = "secretstore-http-cors" + about = "Specify CORS header for Secret Store HTTP API responses. Special options: \"all\", \"none\".", + help_heading = Some(SECRET_STORE), )] pub secretstore_http_cors: Option, - #[structopt( - help = "Secret Store permissioning contract address source: none, registry (contract address is read from 'secretstore_acl_checker' entry in registry) or address.", - long = "secretstore-acl-contract" + #[clap( + long = "secretstore-acl-contract", + about = "Secret Store permissioning contract address source: none, registry (contract address is read from 'secretstore_acl_checker' entry in registry) or address.", + help_heading = Some(SECRET_STORE), )] pub secretstore_acl_contract: Option, - #[structopt( + #[clap( long = "secrestore-contract", name = "SECRETSTORE_SOURCE", - help = "Secret Store Service contract address source: none, registry (contract address is read from 'secretstore_service' entry in registry) or address." + about = "Secret Store Service contract address source: none, registry (contract address is read from 'secretstore_service' entry in registry) or address.", + help_heading = Some(SECRET_STORE), )] pub secretstore_contract: Option, - #[structopt( + #[clap( long = "secretstore-srv-gen-contract", name = "GEN_SOURCE", - help = "Secret Store Service server key generation contract address source: none, registry (contract address is read from 'secretstore_service_srv_gen' entry in registry) or address." + about = "Secret Store Service server key generation contract address source: none, registry (contract address is read from 'secretstore_service_srv_gen' entry in registry) or address.", + help_heading = Some(SECRET_STORE), )] pub secretstore_srv_gen_contract: Option, - #[structopt( - help = "Secret Store Service server key retrieval contract address source: none, registry (contract address is read from 'secretstore_service_srv_retr' entry in registry) or address.", + #[clap( + about = "Secret Store Service server key retrieval contract address source: none, registry (contract address is read from 'secretstore_service_srv_retr' entry in registry) or address.", name = "RETR_SOURCE", - long = "secretstore-srv-retr-contract" + long = "secretstore-srv-retr-contract", + help_heading = Some(SECRET_STORE), )] pub secretstore_srv_retr_contract: Option, - #[structopt( - help = "Secret Store Service document key store contract address source: none, registry (contract address is read from 'secretstore_service_doc_store' entry in registry) or address.", + #[clap( + about = "Secret Store Service document key store contract address source: none, registry (contract address is read from 'secretstore_service_doc_store' entry in registry) or address.", name = "DOC_STORE_SOURCE", - long = "secretstore-doc-store-contract" + long = "secretstore-doc-store-contract", + help_heading = Some(SECRET_STORE), )] pub secretstore_doc_store_contract: Option, - #[structopt( - help = "Secret Store Service document key shadow retrieval contract address source: none, registry (contract address is read from 'secretstore_service_doc_sretr' entry in registry) or address.", + #[clap( + about = "Secret Store Service document key shadow retrieval contract address source: none, registry (contract address is read from 'secretstore_service_doc_sretr' entry in registry) or address.", name = "DOC_SRETR_SOURCE", - long = "secretstore-doc-sretr-contract" + long = "secretstore-doc-sretr-contract", + help_heading = Some(SECRET_STORE), )] pub secretstore_doc_sretr_contract: Option, - #[structopt( - help = "Comma-separated list of other secret store cluster nodes in form NODE_PUBLIC_KEY_IN_HEX@NODE_IP_ADDR:NODE_PORT.", + #[clap( + about = "Comma-separated list of other secret store cluster nodes in form NODE_PUBLIC_KEY_IN_HEX@NODE_IP_ADDR:NODE_PORT.", name = "SECRETSTORE_NODES", - long = "secretstore-nodes" + long = "secretstore-nodes", + help_heading = Some(SECRET_STORE), )] pub secretstore_nodes: Option, - #[structopt( + #[clap( name = "SET_CONTRACT_SOURCE", long = "secretstore-server-set-contract", - help = "Secret Store server set contract address source: none, registry (contract address is read from 'secretstore_server_set' entry in registry) or address." + about = "Secret Store server set contract address source: none, registry (contract address is read from 'secretstore_server_set' entry in registry) or address.", + help_heading = Some(SECRET_STORE), )] pub secretstore_server_set_contract: Option, - #[structopt( - help = "Specify the hostname portion for listening to Secret Store Key Server internal requests, IP should be an interface's IP address, or local.", + #[clap( + long = "secretstore-interface-ip", name = "SECRETSTORE_IP", - long = "secretstore-interface-ip" + about = "Specify the hostname portion for listening to Secret Store Key Server internal requests, IP should be an interface's IP address, or local.", + help_heading = Some(SECRET_STORE), )] pub secretstore_interface: Option, - #[structopt( + #[clap( long = "secretstore-port", name = "SECRETSTORE_PORT", - help = "Specify the port portion for listening to Secret Store Key Server internal requests." + about = "Specify the port portion for listening to Secret Store Key Server internal requests.", + help_heading = Some(SECRET_STORE), )] pub secretstore_port: Option, - #[structopt( + #[clap( long = "secretstore-http-interface", - help = "Specify the hostname portion for listening to Secret Store Key Server HTTP requests, IP should be an interface's IP address, or local.", - name = "SECRETSTORE_HTTP_INTERFACE" + name = "SECRETSTORE_HTTP_INTERFACE", + about = "Specify the hostname portion for listening to Secret Store Key Server HTTP requests, IP should be an interface's IP address, or local.", + help_heading = Some(SECRET_STORE), )] pub secretstore_http_interface: Option, - #[structopt( + #[clap( long = "secretstore-http-port", name = "SECRETSTORE_HTTP_PORT", - help = "Specify the port portion for listening to Secret Store Key Server HTTP requests." + about = "Specify the port portion for listening to Secret Store Key Server HTTP requests.", + help_heading = Some(SECRET_STORE), )] pub secretstore_http_port: Option, - #[structopt( + #[clap( name = "SECRETSTORE_PATH", long = "secretstore-path", - help = "Specify directory where Secret Store should save its data." + about = "Specify directory where Secret Store should save its data.", + help_heading = Some(SECRET_STORE), )] pub secretstore_path: Option, - #[structopt( + #[clap( long = "secretstore-secret", name = "SECRETSTORE_SECRET", - help = "Hex-encoded secret key of this node." + about = "Hex-encoded secret key of this node.", + help_heading = Some(SECRET_STORE), )] pub secretstore_secret: Option, - #[structopt( + #[clap( long = "secretstore-admin-public", name = "SECRETSTORE_ADMIN_PUBLIC", - help = "Hex-encoded public key of secret store administrator." + about = "Hex-encoded public key of secret store administrator.", + help_heading = Some(SECRET_STORE), )] pub secretstore_admin_public: Option, } -#[derive(StructOpt, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] +#[derive(Clap, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] pub struct SealingMiningOptions { - #[structopt( - help = "Force the node to author new blocks as if it were always sealing/mining.", - long = "force-sealing" + #[clap( + about = "Force the node to author new blocks as if it were always sealing/mining.", + long = "force-sealing", + help_heading = Some(SEALING_MINING), )] pub force_sealing: bool, - #[structopt( - help = "Force the node to author new blocks when a new uncle block is imported.", - long = "reseal-on-uncle" + #[clap( + about = "Force the node to author new blocks when a new uncle block is imported.", + long = "reseal-on-uncle", + help_heading = Some(SEALING_MINING), )] pub reseal_on_uncle: bool, - #[structopt( - help = "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.", - long = "remove-solved" + #[clap( + about = "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.", + long = "remove-solved", + help_heading = Some(SEALING_MINING), )] pub remove_solved: bool, - #[structopt( - help = "Local transactions sent through JSON-RPC (HTTP, WebSockets, etc) will be treated as 'external' if the sending account is unknown.", - long = "tx-queue-no-unfamiliar-locals" + #[clap( + about = "Local transactions sent through JSON-RPC (HTTP, WebSockets, etc) will be treated as 'external' if the sending account is unknown.", + long = "tx-queue-no-unfamiliar-locals", + help_heading = Some(SEALING_MINING), )] pub tx_queue_no_unfamiliar_locals: bool, - #[structopt( - help = "Disables transaction queue optimization to early reject transactions below minimal effective gas price. This allows local transactions to always enter the pool, despite it being full, but requires additional ecrecover on every transaction.", - long = "tx-queue-no-early-reject" + #[clap( + about = "Disables transaction queue optimization to early reject transactions below minimal effective gas price. This allows local transactions to always enter the pool, despite it being full, but requires additional ecrecover on every transaction.", + long = "tx-queue-no-early-reject", + help_heading = Some(SEALING_MINING), )] pub tx_queue_no_early_reject: bool, - #[structopt( - help = "Always refuse service transactions.", - long = "refuse-service-transactions" + #[clap( + about = "Always refuse service transactions.", + long = "refuse-service-transactions", + help_heading = Some(SEALING_MINING), )] pub refuse_service_transactions: bool, - #[structopt( - help = "Pending block will be created with maximal possible gas limit and will execute all transactions in the queue. Note that such block is invalid and should never be attempted to be mined.", - long = "infinite-pending-block" + #[clap( + about = "Pending block will be created with maximal possible gas limit and will execute all transactions in the queue. Note that such block is invalid and should never be attempted to be mined.", + long = "infinite-pending-block", + help_heading = Some(SEALING_MINING), )] pub infinite_pending_block: bool, - #[structopt( - help = "Don't save pending local transactions to disk to be restored whenever the node restarts.", - long = "no-persistent-txqueue" + #[clap( + about = "Don't save pending local transactions to disk to be restored whenever the node restarts.", + long = "no-persistent-txqueue", + help_heading = Some(SEALING_MINING), )] pub no_persistent_txqueue: bool, // For backward compatibility; Stratum should be enabled if the config file // contains a `[stratum]` section and it is not explicitly disabled (disable = true) - #[structopt(help = "Run Stratum server for miner push notification.", long)] + #[clap( + long, + about = "Run Stratum server for miner push notification.", + help_heading = Some(SEALING_MINING), + )] pub stratum: bool, - #[structopt( + #[clap( long = "reseal-on-txs", name = "RESEAL_TXS_SET", - help = "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." + about = "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.", + help_heading = Some(SEALING_MINING), )] pub reseal_on_txs: Option, - #[structopt( - help = "Specify the minimum time between reseals from incoming transactions. MS is time measured in milliseconds.", + #[clap( long = "reseal-min-period", - name = "RESEAL_MIN_MS" + name = "RESEAL_MIN_MS", + about = "Specify the minimum time between reseals from incoming transactions. MS is time measured in milliseconds.", + help_heading = Some(SEALING_MINING), )] pub reseal_min_period: Option, - #[structopt( + #[clap( long = "reseal-max-period", name = "RESEAL_MAX_MS", - help = "Specify the maximum time between reseals from incoming transactions. MS is time measured in milliseconds." + about = "Specify the maximum time between reseals from incoming transactions. MS is time measured in milliseconds.", + help_heading = Some(SEALING_MINING), )] pub reseal_max_period: Option, - #[structopt( + #[clap( name = "WORK_QUEUE_SIZE_ITEMS", long = "work-queue-size", - help = "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." + about = "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.", + help_heading = Some(SEALING_MINING), )] pub work_queue_size: Option, - #[structopt( + #[clap( long = "relay-set", name = "RELAY_SET", - help = "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." + about = "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.", + help_heading = Some(SEALING_MINING), )] pub relay_set: Option, - #[structopt( + #[clap( long = "usd-per-tx", name = "USD_PER_TX", - help = "Amount of USD to be paid for a basic transaction. The minimum gas price is set accordingly." + about = "Amount of USD to be paid for a basic transaction. The minimum gas price is set accordingly.", + help_heading = Some(SEALING_MINING), )] pub usd_per_tx: Option, - #[structopt( - help = "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.", + #[clap( + long = "usd-per-eth", name = "USD_PER_ETH_SOURCE", - long = "usd-per-eth" + about = "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.", + help_heading = Some(SEALING_MINING), )] pub usd_per_eth: Option, - #[structopt( + #[clap( long = "price-update-period", name = "PRICE_UPDATE_T", - help = "PRICE_UPDATE_T will be allowed to pass between each gas price update. PRICE_UPDATE_T may be daily, hourly, a number of seconds, or a time string of the form \"2 days\", \"30 minutes\" etc.." + about = "PRICE_UPDATE_T will be allowed to pass between each gas price update. PRICE_UPDATE_T may be daily, hourly, a number of seconds, or a time string of the form \"2 days\", \"30 minutes\" etc..", + help_heading = Some(SEALING_MINING), )] pub price_update_period: Option, - #[structopt( - help = "Amount of gas per block to target when sealing a new block.", + #[clap( long = "gas-floor-target", - name = "GAS_FLOOR" + name = "GAS_FLOOR", + about = "Amount of gas per block to target when sealing a new block.", + help_heading = Some(SEALING_MINING), )] pub gas_floor_target: Option, - #[structopt( - help = "A cap on how large we will raise the gas limit per block due to transaction volume.", + #[clap( long = "gas-cap", - name = "GAS_CAP" + name = "GAS_CAP", + about = "A cap on how large we will raise the gas limit per block due to transaction volume.", + help_heading = Some(SEALING_MINING), )] pub gas_cap: Option, - #[structopt( - help = "Maximum amount of memory that can be used by the transaction queue. Setting this parameter to 0 disables limiting.", + #[clap( long = "tx-queue-mem-limit", - name = "TX_QUEUE_LIMIT_MB" + name = "TX_QUEUE_LIMIT_MB", + about = "Maximum amount of memory that can be used by the transaction queue. Setting this parameter to 0 disables limiting.", + help_heading = Some(SEALING_MINING), )] pub tx_queue_mem_limit: Option, - #[structopt( - help = "Maximum amount of transactions in the queue (waiting to be included in next block).", + #[clap( long = "tx-queue-size", - name = "TX_QUEUE_SIZE_LIMIT" + name = "TX_QUEUE_SIZE_LIMIT", + about = "Maximum amount of transactions in the queue (waiting to be included in next block).", + help_heading = Some(SEALING_MINING), )] pub tx_queue_size: Option, - #[structopt( - help = "Maximum number of transactions per sender in the queue. By default it's 1% of the entire queue, but not less than 16.", + #[clap( long = "tx-queue-per-sender", - name = "TX_QUEUE_PER_SENDER_LIMIT" + name = "TX_QUEUE_PER_SENDER_LIMIT", + about = "Maximum number of transactions per sender in the queue. By default it's 1% of the entire queue, but not less than 16.", + help_heading = Some(SEALING_MINING), )] pub tx_queue_per_sender: Option, - #[structopt( - help = "Specify local accounts for which transactions are prioritized in the queue. ACCOUNTS is a comma-delimited list of addresses.", + #[clap( long = "tx-queue-locals", - name = "TX_QUEUE_LOCAL_ACCOUNTS" + name = "TX_QUEUE_LOCAL_ACCOUNTS", + about = "Specify local accounts for which transactions are prioritized in the queue. ACCOUNTS is a comma-delimited list of addresses.", + help_heading = Some(SEALING_MINING), )] pub tx_queue_locals: Option, - #[structopt( - help = "Prioritization strategy used to order transactions in the queue. S may be: gas_price - Prioritize txs with high gas price", + #[clap( long = "tx-queue-strategy", - name = "TX_QUEUE_S" + name = "TX_QUEUE_S", + about = "Prioritization strategy used to order transactions in the queue. S may be: gas_price - Prioritize txs with high gas price", + help_heading = Some(SEALING_MINING), )] pub tx_queue_strategy: Option, - #[structopt( - help = "Interface address for Stratum server.", + #[clap( long = "stratum-interface", - name = "STRATUM_IP" + name = "STRATUM_IP", + about = "Interface address for Stratum server.", + help_heading = Some(SEALING_MINING), )] pub stratum_interface: Option, - #[structopt( - help = "Port for Stratum server to listen on.", + #[clap( long = "stratum-port", - name = "STRATUM_PORT" + name = "STRATUM_PORT", + about = "Port for Stratum server to listen on.", + help_heading = Some(SEALING_MINING), )] pub stratum_port: Option, - #[structopt( - help = "Minimum amount of Wei per GAS to be paid for a transaction to be accepted for mining. Overrides --usd-per-tx.", + #[clap( long = "min-gas-price", - name = "MIN_GAS_PRICE_STRING" + name = "MIN_GAS_PRICE_STRING", + about = "Minimum amount of Wei per GAS to be paid for a transaction to be accepted for mining. Overrides --usd-per-tx.", + help_heading = Some(SEALING_MINING), )] pub min_gas_price: Option, - #[structopt( - help = "Set PCT percentile gas price value from last 100 blocks as default gas price when sending transactions.", + #[clap( long = "gas-price-percentile", - name = "PCT" + name = "PCT", + about = "Set PCT percentile gas price value from last 100 blocks as default gas price when sending transactions.", + help_heading = Some(SEALING_MINING), )] pub gas_price_percentile: Option, - #[structopt( - help = "Specify the block author (aka \"coinbase\") address for sending block rewards from sealed blocks. NOTE: MINING WILL NOT WORK WITHOUT THIS OPTION.", + #[clap( long, - name = "ADDRESS" + name = "ADDRESS", + about = "Specify the block author (aka \"coinbase\") address for sending block rewards from sealed blocks. NOTE: MINING WILL NOT WORK WITHOUT THIS OPTION.", + help_heading = Some(SEALING_MINING), )] pub author: Option, // Sealing / Mining Option - #[structopt( - help = "Specify the address which should be used to sign consensus messages and issue blocks. Relevant only to non-PoW chains.", + #[clap( long = "engine-signer", - name = "ENGINE_SIGNER_ADDRESS" + name = "ENGINE_SIGNER_ADDRESS", + about = "Specify the address which should be used to sign consensus messages and issue blocks. Relevant only to non-PoW chains.", + help_heading = Some(SEALING_MINING), )] pub engine_signer: Option, - #[structopt( - help = "Apply a limit of GAS as the maximum amount of gas a single transaction may have for it to be mined.", + #[clap( long = "tx-gas-limit", - name = "TX_GAS_LIMIT" + name = "TX_GAS_LIMIT", + about = "Apply a limit of GAS as the maximum amount of gas a single transaction may have for it to be mined.", + help_heading = Some(SEALING_MINING), )] pub tx_gas_limit: Option, - #[structopt( - help = "Maximal time for processing single transaction. If enabled senders of transactions offending the limit will get other transactions penalized.", + #[clap( long = "tx-time-limit", - name = "TX_TIME_LIMIT_MS" + name = "TX_TIME_LIMIT_MS", + about = "Maximal time for processing single transaction. If enabled senders of transactions offending the limit will get other transactions penalized.", + help_heading = Some(SEALING_MINING), )] pub tx_time_limit: Option, - #[structopt( + #[clap( long = "extra-data", - help = "Specify a custom extra-data for authored blocks, no more than 32 characters.", - name = "EXTRA_DATA_STRING" + name = "EXTRA_DATA_STRING", + about = "Specify a custom extra-data for authored blocks, no more than 32 characters.", + help_heading = Some(SEALING_MINING), )] pub extra_data: Option, - #[structopt( + #[clap( + long = "notify-work", name = "NOTIFY_WORK_URLS", - help = "URLs to which work package notifications are pushed. URLS should be a comma-delimited list of HTTP URLs.", - long = "notify-work" + about = "URLs to which work package notifications are pushed. URLS should be a comma-delimited list of HTTP URLs.", + help_heading = Some(SEALING_MINING), )] pub notify_work: Option, - #[structopt( - name = "STARTUM_SECRET_STRING", + #[clap( long = "stratum-secret", - help = "Secret for authorizing Stratum server for peers." + name = "STARTUM_SECRET_STRING", + about = "Secret for authorizing Stratum server for peers.", + help_heading = Some(SEALING_MINING), )] pub stratum_secret: Option, - #[structopt( + #[clap( long = "max-round-blocks-to-import", name = "MAX_ROUND_BLOCKS_S", - help = "Maximal number of blocks to import for each import round." + about = "Maximal number of blocks to import for each import round.", + help_heading = Some(SEALING_MINING), )] pub max_round_blocks_to_import: Option, } -#[derive(StructOpt, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] +#[derive(Clap, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] pub struct InternalOptions { - #[structopt( + #[clap( long = "can-restart", - help = "Executable will auto-restart if exiting with 69" + about = "Executable will auto-restart if exiting with 69", + help_heading = Some(INTERNAL), )] pub can_restart: bool, } -#[derive(StructOpt, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] +#[derive(Clap, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] pub struct MiscellaneousOptions { - #[structopt(help = "Don't use terminal color codes in output.", long = "no-color")] + #[clap( + long = "no-color", + about = "Don't use terminal color codes in output.", + help_heading = Some(MISCELLANEOUS), + )] pub no_color: bool, // version flag is automatically provided by structopt - #[structopt(long = "no-config", help = "Don't load a configuration file.")] + #[clap( + long = "no-config", + about = "Don't load a configuration file.", + help_heading = Some(MISCELLANEOUS), + )] pub no_config: bool, - #[structopt( + #[clap( short = "l", long, name = "LOGGING", - help = "Specify the general logging level (error, warn, info, debug or trace). It can also be set for a specific module, example: '-l sync=debug,rpc=trace'" + about = "Specify the general logging level (error, warn, info, debug or trace). It can also be set for a specific module, example: '-l sync=debug,rpc=trace'", + help_heading = Some(MISCELLANEOUS), )] pub logging: Option, - #[structopt( + #[clap( long = "log-file", name = "LOG_FILENAME", - help = "Specify a filename into which logging should be appended" + about = "Specify a filename into which logging should be appended", + help_heading = Some(MISCELLANEOUS), )] pub log_file: Option, } -#[derive(StructOpt, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] +#[derive(Clap, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] pub struct FootPrintOptions { - #[structopt( - help = "Automatically scale amount of verifier threads based on workload. Not guaranteed to be faster.", - long = "scale-verifiers" + #[clap( + long = "scale-verifiers", + about = "Automatically scale amount of verifier threads based on workload. Not guaranteed to be faster.", + help_heading = Some(FOOTPRINT), )] pub scale_verifiers: bool, - #[structopt( - help = "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).", + #[clap( long, - name = "TRACING_BOOL" + name = "TRACING_BOOL", + about = "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).", + help_heading = Some(FOOTPRINT), )] pub tracing: Option, - #[structopt( + #[clap( long, name = "PRUNING_METHOD", - help = "Configure pruning of the state/storage trie. PRUNING_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." + about = "Configure pruning of the state/storage trie. PRUNING_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.", + help_heading = Some(FOOTPRINT), )] pub pruning: Option, - #[structopt( + #[clap( long = "pruning-history", - help = "Set a minimum number of recent states to keep in memory when pruning is active.", - name = "PRUNING_HISTORY_NUM" + name = "PRUNING_HISTORY_NUM", + about = "Set a minimum number of recent states to keep in memory when pruning is active.", + help_heading = Some(FOOTPRINT), )] pub pruning_history: Option, - #[structopt( + #[clap( long = "pruning-memory", name = "PRUNING_MEMORY_MB", - help = "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." + about = "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.", + help_heading = Some(FOOTPRINT), )] pub pruning_memory: Option, - #[structopt( - help = "Override database cache size.", + #[clap( long = "cache-size-db", - name = "CACHE_SIZE_DB_MB" + name = "CACHE_SIZE_DB_MB", + about = "Override database cache size.", + help_heading = Some(FOOTPRINT), )] pub cache_size_db: Option, - #[structopt( - help = "Specify the preferred size of the blockchain cache in megabytes.", + #[clap( long = "cache-size-blocks", - name = "CACHE_SIZE_BLOCKS_MB" + name = "CACHE_SIZE_BLOCKS_MB", + about = "Specify the preferred size of the blockchain cache in megabytes.", + help_heading = Some(FOOTPRINT), )] pub cache_size_blocks: Option, - #[structopt( - help = "Specify the maximum size of memory to use for block queue.", + #[clap( long = "cache-size-queue", - name = "CACHE_SIZE_QUEUE_MB" + name = "CACHE_SIZE_QUEUE_MB", + about = "Specify the maximum size of memory to use for block queue.", + help_heading = Some(FOOTPRINT), )] pub cache_size_queue: Option, - #[structopt( - help = "Specify the maximum size of memory to use for the state cache.", + #[clap( long = "cache-size-state", - name = "CACHE_SIZE_STATE" + name = "CACHE_SIZE_STATE", + about = "Specify the maximum size of memory to use for the state cache.", + help_heading = Some(FOOTPRINT), )] pub cache_size_state: Option, - #[structopt( - help = "Database compaction type. TYPE may be one of: ssd - suitable for SSDs and fast HDDs; hdd - suitable for slow HDDs; auto - determine automatically.", + #[clap( long = "db-compaction", - name = "DB_COMPACTION_TYPE" + name = "DB_COMPACTION_TYPE", + about = "Database compaction type. TYPE may be one of: ssd - suitable for SSDs and fast HDDs; hdd - suitable for slow HDDs; auto - determine automatically.", + help_heading = Some(FOOTPRINT), )] pub db_compaction: Option, - #[structopt( - help = "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.", + #[clap( long = "fat-db", - name = "FAT_DB_BOOL" + name = "FAT_DB_BOOL", + about = "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.", + help_heading = Some(FOOTPRINT), )] pub fat_db: Option, - #[structopt( - help = "Set total amount of discretionary memory to use for the entire system, overrides other cache and queue options.", + #[clap( long = "cache-size", - name = "CACHE_SIZE_MB" + name = "CACHE_SIZE_MB", + about = "Set total amount of discretionary memory to use for the entire system, overrides other cache and queue options.", + help_heading = Some(FOOTPRINT), )] pub cache_size: Option, - #[structopt( - help = "Amount of verifier threads to use or to begin with, if verifier auto-scaling is enabled.", + #[clap( name = "NUM_VERIFIERS_INT", - long = "num-verifiers" + long = "num-verifiers", + about = "Amount of verifier threads to use or to begin with, if verifier auto-scaling is enabled.", + help_heading = Some(FOOTPRINT), )] pub num_verifiers: Option, } -#[derive(StructOpt, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] +#[derive(Clap, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] pub struct ImportExportOptions { - #[structopt(long = "no-seal-check", help = "Skip block seal check.")] + #[clap( + long = "no-seal-check", + about = "Skip block seal check.", + help_heading = Some(IMPORT_EXPORT), + )] pub no_seal_check: bool, } -#[derive(StructOpt, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] +#[derive(Clap, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] pub struct SnapshotOptions { - #[structopt( - help = "Disable automated snapshots which usually occur once every 5000 blocks.", - long = "no-periodic-snapshots" + #[clap( + long = "no-periodic-snapshots", + about = "Disable automated snapshots which usually occur once every 5000 blocks.", + help_heading = Some(SNAPSHOT), )] pub no_periodic_snapshot: bool, - #[structopt( - help = "Enables multiple threads for snapshots creation.", + #[clap( long = "snapshot-threads", - name = "SNAPSHOT_THREADS_NUM" + name = "SNAPSHOT_THREADS_NUM", + about = "Enables multiple threads for snapshots creation.", + help_heading = Some(SNAPSHOT), )] pub snapshot_threads: Option, } -#[derive(StructOpt, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] +#[derive(Clap, Serialize, Deserialize, Debug, Clone, PartialEq, Default)] pub struct LegacyOptions { // TODO: These options were hidden from config, so should we not include them? - #[structopt( + #[clap( long, - help = "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." + about = "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.", + help_heading = Some(LEGACY), )] pub geth: bool, - #[structopt( - help = "Attempt to import keys from Geth client.", - long = "import-geth-keys" + #[clap( + long = "import-geth-keys", + about = "Attempt to import keys from Geth client.", + help_heading = Some(LEGACY), )] pub import_geth_keys: bool, } diff --git a/parity/cli/parse_cli.rs b/parity/cli/parse_cli.rs index 182b45c19ea..d1c5bc024cf 100644 --- a/parity/cli/parse_cli.rs +++ b/parity/cli/parse_cli.rs @@ -1,12 +1,17 @@ -use structopt::StructOpt; - +use clap::{AppSettings::*, Clap}; use cli::globals::Globals; use cli::subcommands::SubCommands; -#[derive(StructOpt, Debug, Clone, Default)] +/// OpenEthereum +#[derive(Clap, Debug, Clone, Default)] +#[clap( + name = "OpenEthereum", + about = "Fast and feature-rich multi-network Ethereum client.", + setting = DeriveDisplayOrder, +)] pub struct ArgsInput { - #[structopt(subcommand)] + #[clap(subcommand)] pub subcommands: Option, - #[structopt(flatten)] + #[clap(flatten)] pub globals: Globals, } diff --git a/parity/cli/subcommands.rs b/parity/cli/subcommands.rs index ea0322be1cf..d8b7d1b4eb0 100644 --- a/parity/cli/subcommands.rs +++ b/parity/cli/subcommands.rs @@ -1,49 +1,49 @@ use serde_derive::Deserialize; -use structopt::StructOpt; +use clap::Clap; -#[derive(StructOpt, Deserialize, Debug, Clone)] +#[derive(Clap, Deserialize, Debug, Clone)] pub enum SubCommands { Daemon(Daemon), Wallet { - #[structopt(subcommand)] + #[clap(subcommand)] wallet: Wallet, }, Account { - #[structopt(subcommand)] + #[clap(subcommand)] account: Account, }, Import(Import), Export { - #[structopt(subcommand)] + #[clap(subcommand)] export: Export, }, Signer(Signer), Snapshots(Snapshots), Restore(Restore), Db(Db), - #[structopt( + #[clap( about = "Print the hashed light clients headers of the given --chain (default: mainnet) in a JSON format. To be used as hardcoded headers in a genesis file." )] ExportHardcodedSync, } -#[derive(StructOpt, Deserialize, Debug, Clone)] -#[structopt(about = "Use parity as a daemon")] +#[derive(Clap, Deserialize, Debug, Clone)] +#[clap(about = "Use parity as a daemon")] pub struct Daemon { - #[structopt(long = "pid-file", name = "PID-FILE", help = "Path to the pid file")] + #[clap(long = "pid-file", name = "PID-FILE", about = "Path to the pid file")] pub pid_file: Option, } -#[derive(StructOpt, Deserialize, Debug, Clone)] -#[structopt(about = "Manage accounts")] +#[derive(Clap, Deserialize, Debug, Clone)] +#[clap(about = "Manage accounts")] pub enum Account { - #[structopt( + #[clap( about = "Create a new account (and its associated key) for the given --chain [default: mainnet]" )] New, - #[structopt(about = "List existing accounts of the given --chain [default: mainnet]")] + #[clap(about = "List existing accounts of the given --chain [default: mainnet]")] List, - #[structopt( + #[clap( about = "Import accounts from JSON UTC keystore files to the specified --chain [default: mainnet]" )] // FIXME: The original parser implementation had this as `Option>` but this is not @@ -52,171 +52,171 @@ pub enum Account { Import { path: Vec }, } -#[derive(StructOpt, Deserialize, Debug, Clone)] -#[structopt(about = "Manage wallet")] +#[derive(Clap, Deserialize, Debug, Clone)] +#[clap(about = "Manage wallet")] pub enum Wallet { - #[structopt(help = "Import wallet into the given chain (default: mainnet)")] + #[clap(about = "Import wallet into the given chain (default: mainnet)")] Import { - #[structopt(name = "PATH", help = "Path to the wallet")] + #[clap(name = "PATH", about = "Path to the wallet")] path: Option, }, } -#[derive(StructOpt, Deserialize, Debug, Clone)] -#[structopt( +#[derive(Clap, Deserialize, Debug, Clone)] +#[clap( about = "Import blockchain data from a file to the given chain database (default: mainnet)" )] pub struct Import { - #[structopt( + #[clap( long, name = "FORMAT", - help = "Import in a given format, FORMAT must be either 'hex' or 'binary'. (default: auto)" + about = "Import in a given format, FORMAT must be either 'hex' or 'binary'. (default: auto)" )] pub format: Option, - #[structopt(name = "FILE", long, help = "Path to the file to import from")] + #[clap(name = "FILE", long, about = "Path to the file to import from")] pub file: Option, } -#[derive(StructOpt, Deserialize, Debug, Clone)] -#[structopt(about = "Export blockchain")] +#[derive(Clap, Deserialize, Debug, Clone)] +#[clap(about = "Export blockchain")] pub enum Export { Blocks(ExportBlocks), State(ExportState), } -#[derive(StructOpt, Deserialize, Debug, Clone)] -#[structopt( +#[derive(Clap, Deserialize, Debug, Clone)] +#[clap( about = "Export the blockchain blocks from the given chain database [default: mainnet] into a file. The command requires the chain to be synced with --fat-db on." )] pub struct ExportBlocks { - #[structopt( + #[clap( long, name = "FORMAT", - help = "Export in a given format. FORMAT must be 'hex' or 'binary'. [default: binary]" + about = "Export in a given format. FORMAT must be 'hex' or 'binary'. [default: binary]" )] pub format: Option, - #[structopt( + #[clap( long, name = "FROM_BLOCK", - help = "Export from block FROM_BLOCK, which may be an index or hash ", + about = "Export from block FROM_BLOCK, which may be an index or hash ", default_value = "1" )] pub from: String, - #[structopt( + #[clap( long, name = "TO_BLOCK", - help = "Export to (including TO_BLOCK) block TO_BLOCK, which may be an index, hash or 'latest'", + about = "Export to (including TO_BLOCK) block TO_BLOCK, which may be an index, hash or 'latest'", default_value = "latest" )] pub to: String, - #[structopt(help = "Path to the exported file", name = "FILE")] + #[clap(about = "Path to the exported file", name = "FILE")] pub file: Option, } -#[derive(StructOpt, Deserialize, Debug, Clone)] -#[structopt( +#[derive(Clap, Deserialize, Debug, Clone)] +#[clap( about = "Export the blockchain state from the given chain [default: mainnet] into a file. The command requires the chain to be synced with --fat-db on." )] pub struct ExportState { - #[structopt(long = "no-storage", help = "Don't export account storage.")] + #[clap(long = "no-storage", about = "Don't export account storage.")] pub no_storage: bool, - #[structopt(long = "no-code", help = "Don't export account code.")] + #[clap(long = "no-code", about = "Don't export account code.")] pub no_code: bool, - #[structopt( + #[clap( long = "max-balance", name = "MAX_WEI", - help = "Don't export accounts with balance greater than specified." + about = "Don't export accounts with balance greater than specified." )] pub max_balance: Option, - #[structopt( + #[clap( long = "min-balance", name = "MIN_WEI", - help = "Don't export accounts with balance less than specified." + about = "Don't export accounts with balance less than specified." )] pub min_balance: Option, - #[structopt( + #[clap( default_value = "latest", long, name = "BLOCK", - help = "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" + about = "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" )] pub at: String, - #[structopt( + #[clap( long, name = "FORMAT", - help = "Export in a given format. FORMAT must be either 'hex' or 'binary'. [default: binary]" + about = "Export in a given format. FORMAT must be either 'hex' or 'binary'. [default: binary]" )] pub format: Option, - #[structopt(long = "file", name = "FILE", help = "Path to the exported file")] + #[clap(long = "file", name = "FILE", about = "Path to the exported file")] pub file: Option, } -#[derive(StructOpt, Deserialize, Debug, Clone)] -#[structopt(about = "Manage Signer")] +#[derive(Clap, Deserialize, Debug, Clone)] +#[clap(about = "Manage Signer")] pub enum Signer { - #[structopt( + #[clap( about = "Generate a new signer-authentication token for the given --chain (default: mainnet)" )] NewToken, - #[structopt( + #[clap( about = "List the signer-authentication tokens from given --chain (default: mainnet)" )] List, - #[structopt(about = "Sign")] + #[clap(about = "Sign")] Sign { - #[structopt(name = "ID")] + #[clap(name = "ID")] id: Option, }, - #[structopt(about = "Reject")] + #[clap(about = "Reject")] Reject { - #[structopt(name = "ID")] + #[clap(name = "ID")] id: Option, }, } -#[derive(StructOpt, Deserialize, Debug, Clone)] -#[structopt(about = "Make a snapshot of the database of the given chain (default: mainnet)")] +#[derive(Clap, Deserialize, Debug, Clone)] +#[clap(about = "Make a snapshot of the database of the given chain (default: mainnet)")] pub struct Snapshots { - #[structopt( + #[clap( default_value = "latest", name = "BLOCK", - help = "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" + about = "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" )] pub at: String, - #[structopt(name = "FILE", help = "Path to the file to export to")] + #[clap(name = "FILE", about = "Path to the file to export to")] pub file: Option, } -#[derive(StructOpt, Deserialize, Debug, Clone)] -#[structopt( +#[derive(Clap, Deserialize, Debug, Clone)] +#[clap( about = "Restore the databse of the given chain (default: mainnet) from a snapshot file" )] pub struct Restore { - #[structopt(name = "FILE", help = "Path to the file to restore from")] + #[clap(name = "FILE", about = "Path to the file to restore from")] pub file: Option, } -#[derive(StructOpt, Deserialize, Debug, Clone)] -#[structopt(about = "Manage the Database representing the state of the blockchain on this system")] +#[derive(Clap, Deserialize, Debug, Clone)] +#[clap(about = "Manage the Database representing the state of the blockchain on this system")] pub enum Db { - #[structopt(about = "Clean the database of the given --chain (default: mainnet)")] + #[clap(about = "Clean the database of the given --chain (default: mainnet)")] Kill, - #[structopt(about = "Removes NUM latests blocks from the db")] + #[clap(about = "Removes NUM latests blocks from the db")] Reset { - #[structopt( + #[clap( default_value = "10", - name = "NUM", - help = "Number of blocks to revert" + name = "REVERT_NUM", + about = "Number of blocks to revert" )] num: u32, }, diff --git a/parity/cli/tests/test_cli.rs b/parity/cli/tests/test_cli.rs index 0a3865fb5fc..969ef936325 100644 --- a/parity/cli/tests/test_cli.rs +++ b/parity/cli/tests/test_cli.rs @@ -34,7 +34,7 @@ fn test_overwrite_custom_config_with_raw_flags() { let (user_defaults, fallback) = Args::generate_default_configuration("test_config.toml", "config_default.toml").unwrap(); - resolved.absorb_cli(raw, user_defaults, fallback); + resolved.absorb_cli(raw, user_defaults, fallback).unwrap(); assert_eq!(resolved.arg_stratum_secret, Some("Changed".to_owned())); } diff --git a/parity/configuration.rs b/parity/configuration.rs index 760efed9f0d..331638547e4 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -61,7 +61,7 @@ pub const ETHERSCAN_ETH_PRICE_ENDPOINT: &str = "https://api.etherscan.io/api?mod #[derive(Debug, PartialEq)] pub enum Cmd { Run(RunCmd), - // Version, // NOTE: this is automatically handled by structopt + // Version, // NOTE: this is automatically handled by Clap Account(AccountCmd), ImportPresaleWallet(ImportWallet), Blockchain(BlockchainCmd), @@ -467,47 +467,47 @@ impl Configuration { } } - pub fn chain(&self) -> Result { + fn chain(&self) -> Result { let name = self.args.arg_chain.clone(); Ok(name.parse()?) } - pub fn is_dev_chain(&self) -> Result { + fn is_dev_chain(&self) -> Result { Ok(self.chain()? == SpecType::Dev) } - pub fn max_peers(&self) -> u32 { + fn max_peers(&self) -> u32 { self.args.arg_max_peers .or(cmp::max(self.args.arg_min_peers, Some(DEFAULT_MAX_PEERS))) .unwrap_or(DEFAULT_MAX_PEERS) as u32 } - pub fn ip_filter(&self) -> Result { + fn ip_filter(&self) -> Result { match IpFilter::parse(self.args.arg_allow_ips.as_str()) { Ok(allow_ip) => Ok(allow_ip), Err(_) => Err("Invalid IP filter value".to_owned()), } } - pub fn min_peers(&self) -> u32 { + fn min_peers(&self) -> u32 { self.args.arg_min_peers .or(cmp::min(self.args.arg_max_peers, Some(DEFAULT_MIN_PEERS))) .unwrap_or(DEFAULT_MIN_PEERS) as u32 } - pub fn max_pending_peers(&self) -> u32 { + fn max_pending_peers(&self) -> u32 { self.args.arg_max_pending_peers as u32 } - pub fn snapshot_peers(&self) -> u32 { + fn snapshot_peers(&self) -> u32 { self.args.arg_snapshot_peers as u32 } - pub fn work_notify(&self) -> Vec { + fn work_notify(&self) -> Vec { self.args.arg_notify_work.as_ref().map_or_else(Vec::new, |s| s.split(',').map(|s| s.to_owned()).collect()) } - pub fn accounts_config(&self) -> Result { + fn accounts_config(&self) -> Result { let cfg = AccountsConfig { iterations: self.args.arg_keys_iterations, refresh_time: self.args.arg_accounts_refresh, @@ -520,7 +520,7 @@ impl Configuration { Ok(cfg) } - pub fn stratum_options(&self) -> Result, String> { + fn stratum_options(&self) -> Result, String> { if self.args.flag_stratum { Ok(Some(stratum::Options { io_path: self.directories().db, @@ -532,7 +532,7 @@ impl Configuration { } - pub fn miner_options(&self) -> Result { + fn miner_options(&self) -> Result { let is_dev_chain = self.is_dev_chain()?; if is_dev_chain && self.args.flag_force_sealing && self.args.arg_reseal_min_period == 0 { return Err("Force sealing can't be used with reseal_min_period = 0".into()); @@ -565,7 +565,7 @@ impl Configuration { Ok(options) } - pub fn pool_limits(&self) -> Result { + fn pool_limits(&self) -> Result { let max_count = self.args.arg_tx_queue_size; Ok(pool::Options { @@ -579,7 +579,7 @@ impl Configuration { }) } - pub fn pool_verification_options(&self) -> Result{ + fn pool_verification_options(&self) -> Result{ Ok(pool::verifier::Options { // NOTE min_gas_price and block_gas_limit will be overwritten right after start. minimal_gas_price: U256::from(20_000_000) * 1_000u32, @@ -592,7 +592,7 @@ impl Configuration { }) } - pub fn secretstore_config(&self) -> Result { + fn secretstore_config(&self) -> Result { Ok(SecretStoreConfiguration { enabled: self.secretstore_enabled(), http_enabled: self.secretstore_http_enabled(), @@ -616,7 +616,7 @@ impl Configuration { }) } - pub fn gas_pricer_config(&self) -> Result { + fn gas_pricer_config(&self) -> Result { fn wei_per_gas(usd_per_tx: f32, usd_per_eth: f32) -> U256 { let wei_per_usd: f32 = 1.0e18 / usd_per_eth; let gas_per_tx: f32 = 21000.0; @@ -657,7 +657,7 @@ impl Configuration { } } - pub fn extra_data(&self) -> Result { + fn extra_data(&self) -> Result { match self.args.arg_extra_data.as_ref() { Some(x) if x.len() <= 32 => Ok(x.as_bytes().to_owned()), None => Ok(version_data()), @@ -665,7 +665,7 @@ impl Configuration { } } - pub fn init_reserved_nodes(&self) -> Result, String> { + fn init_reserved_nodes(&self) -> Result, String> { use std::fs::File; match self.args.arg_reserved_peers { @@ -691,7 +691,7 @@ impl Configuration { } } - pub fn net_addresses(&self) -> Result<(SocketAddr, Option), String> { + fn net_addresses(&self) -> Result<(SocketAddr, Option), String> { let port = self.args.arg_ports_shift + self.args.arg_port; let listen_address = SocketAddr::new(self.interface(&self.args.arg_interface).parse().unwrap(), port); let public_address = if self.args.arg_nat.starts_with("extip:") { @@ -713,7 +713,7 @@ impl Configuration { Ok((listen_address, public_address)) } - pub fn net_config(&self) -> Result { + fn net_config(&self) -> Result { let mut ret = NetworkConfiguration::new(); ret.nat_enabled = self.args.arg_nat == "any" || self.args.arg_nat == "upnp" || self.args.arg_nat == "natpmp"; ret.nat_type = match &self.args.arg_nat[..] { @@ -756,11 +756,11 @@ impl Configuration { Ok(ret) } - pub fn network_id(&self) -> Option { + fn network_id(&self) -> Option { self.args.arg_network_id } - pub fn rpc_apis(&self) -> String { + fn rpc_apis(&self) -> String { let mut apis: Vec<&str> = self.args.arg_jsonrpc_apis.split(",").collect(); if self.args.flag_geth { @@ -770,7 +770,7 @@ impl Configuration { apis.join(",") } - pub fn cors(cors: &str) -> Option> { + fn cors(cors: &str) -> Option> { match cors { "none" => return Some(Vec::new()), "*" | "all" | "any" => return None, @@ -780,7 +780,7 @@ impl Configuration { Some(cors.split(',').map(Into::into).collect()) } - pub fn rpc_cors(&self) -> Option> { + fn rpc_cors(&self) -> Option> { let cors = self.args.arg_jsonrpc_cors.to_owned(); Self::cors(&cors) } @@ -807,7 +807,7 @@ impl Configuration { Some(hosts) } - pub fn rpc_hosts(&self) -> Option> { + fn rpc_hosts(&self) -> Option> { self.hosts(&self.args.arg_jsonrpc_hosts, &self.rpc_interface()) } @@ -843,7 +843,7 @@ impl Configuration { Ok(conf) } - pub fn http_config(&self) -> Result { + fn http_config(&self) -> Result { let mut conf = HttpConfiguration::default(); conf.enabled = self.rpc_enabled(); conf.interface = self.rpc_interface(); @@ -862,7 +862,7 @@ impl Configuration { Ok(conf) } - pub fn ws_config(&self) -> Result { + fn ws_config(&self) -> Result { let support_token_api = // enabled when not unlocking self.args.arg_unlock.is_none() && self.args.arg_enable_signing_queue; @@ -882,7 +882,7 @@ impl Configuration { Ok(conf) } - pub fn private_provider_config(&self) -> Result<(ProviderConfig, EncryptorConfig, bool), String> { + fn private_provider_config(&self) -> Result<(ProviderConfig, EncryptorConfig, bool), String> { let dirs = self.directories(); let provider_conf = ProviderConfig { validator_accounts: to_addresses(&self.args.arg_private_validators)?, @@ -903,7 +903,7 @@ impl Configuration { Ok((provider_conf, encryptor_conf, self.args.flag_private_enabled)) } - pub fn snapshot_config(&self) -> Result { + fn snapshot_config(&self) -> Result { let mut conf = SnapshotConfiguration::default(); conf.no_periodic = self.args.flag_no_periodic_snapshot; if let Some(threads) = self.args.arg_snapshot_threads { @@ -915,7 +915,7 @@ impl Configuration { Ok(conf) } - pub fn network_settings(&self) -> Result { + fn network_settings(&self) -> Result { let http_conf = self.http_config()?; let net_addresses = self.net_addresses()?; Ok(NetworkSettings { @@ -929,7 +929,7 @@ impl Configuration { }) } - pub fn update_policy(&self) -> Result { + fn update_policy(&self) -> Result { Ok(UpdatePolicy { enable_downloading: !self.args.flag_no_download, require_consensus: !self.args.flag_no_consensus, @@ -952,7 +952,7 @@ impl Configuration { }) } - pub fn directories(&self) -> Directories { + fn directories(&self) -> Directories { let local_path = default_local_path(); let default_data_path = default_data_path(); let base_path: &str = match &self.args.arg_base_path { @@ -991,7 +991,7 @@ impl Configuration { } } - pub fn ipc_path(&self) -> String { + fn ipc_path(&self) -> String { parity_ipc_path( &self.directories().base, &self.args.arg_ipc_path.clone(), @@ -999,7 +999,7 @@ impl Configuration { ) } - pub fn interface(&self, interface: &str) -> String { + fn interface(&self, interface: &str) -> String { if self.args.flag_unsafe_expose { return "0.0.0.0".into(); } @@ -1011,24 +1011,24 @@ impl Configuration { }.into() } - pub fn rpc_interface(&self) -> String { + fn rpc_interface(&self) -> String { let rpc_interface = self.args.arg_jsonrpc_interface.clone(); self.interface(&rpc_interface) } - pub fn ws_interface(&self) -> String { + fn ws_interface(&self) -> String { self.interface(&self.args.arg_ws_interface) } - pub fn secretstore_interface(&self) -> String { + fn secretstore_interface(&self) -> String { self.interface(&self.args.arg_secretstore_interface) } - pub fn secretstore_http_interface(&self) -> String { + fn secretstore_http_interface(&self) -> String { self.interface(&self.args.arg_secretstore_http_interface) } - pub fn secretstore_cors(&self) -> Option> { + fn secretstore_cors(&self) -> Option> { Self::cors(self.args.arg_secretstore_http_cors.as_ref()) } @@ -1145,3 +1145,1149 @@ fn into_secretstore_service_contract_address(s: Option<&String>) -> Result Ok(Some(SecretStoreContractAddress::Address(a.parse().map_err(|e| format!("{}", e))?))), } } + +#[cfg(test)] +mod test_configuration{ + use cli::args::Args; + use cli::parse_cli::ArgsInput; + use cli::globals::Globals; + use ethcore_logger::Config as LogConfig; + use configuration::{Configuration, Cmd}; + use std::time::Duration; + use params::{GasPricerConfig}; + use cache::CacheConfig; + + use std::str::FromStr; + + use ethcore::miner::MinerOptions; + use miner::pool::PrioritizationStrategy; + use parity_rpc::NetworkSettings; + use updater::{UpdatePolicy, UpdateFilter, ReleaseTrack}; + use types::ids::BlockId; + use types::data_format::DataFormat; + use account::{AccountCmd, NewAccount, ImportAccounts, ListAccounts}; + use blockchain::{BlockchainCmd, ImportBlockchain, ExportBlockchain, ExportState}; + use dir::{Directories, default_hypervisor_path}; + use helpers::{default_network_config}; + use params::SpecType; + use presale::ImportWallet; + use rpc::WsConfiguration; + use rpc_apis::ApiSet; + use run::RunCmd; + + use network::{AllowIP, IpFilter}; + + extern crate ipnetwork; + use self::ipnetwork::IpNetwork; + + use super::*; + + + fn intialize_with_out_of_the_box_defaults() -> (Args, ArgsInput, Globals, Globals) { + let raw: ArgsInput = Default::default(); + let resolved: Args = Default::default(); + let (user_defaults, fallback) = Args::generate_default_configuration( + "config_default.toml", + "config_default.toml" + ).unwrap(); + + (resolved, raw, user_defaults, fallback) + } + + #[test] + fn test_subcommand_account_new() { + let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + conf.cmd_account = true; + conf.cmd_account_new = true; + + let conf = Configuration { + args: conf, + }; + + let conf: Cmd = conf.into_command().unwrap().cmd; + + let cmd_arg: Cmd = Cmd::Account( + AccountCmd::New(NewAccount{ + iterations: 10240, + path: Directories::default().keys, + password_file: None, + spec: SpecType::default(), + })); + + assert_eq!(conf, cmd_arg); + + } + + #[test] + fn test_command_account_list() { + let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + + conf.cmd_account = true; + conf.cmd_account_list = true; + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + let conf = Configuration { + args: conf, + }; + + let conf: Cmd = conf.into_command().unwrap().cmd; + + let cmd_arg: Cmd = Cmd::Account( + AccountCmd::List(ListAccounts { + path: Directories::default().keys, + spec: SpecType::default(), + })); + + assert_eq!(conf, cmd_arg); + + } + + #[test] + fn test_command_account_import() { + + let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + conf.cmd_account = true; + conf.cmd_account_import = true; + conf.arg_account_import_path = Some(vec!["my_dir".into(), "another_dir".into()]); + + let conf = Configuration { + args: conf, + }; + + let conf: Cmd = conf.into_command().unwrap().cmd; + + let cmd_arg: Cmd = Cmd::Account(AccountCmd::Import(ImportAccounts { + from: vec!["my_dir".into(), "another_dir".into()], + to: Directories::default().keys, + spec: SpecType::default(), + })); + + assert_eq!(conf, cmd_arg); + } + + #[test] + fn test_command_wallet_import() { + let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + conf.cmd_wallet = true; + conf.cmd_wallet_import = true; + conf.arg_wallet_import_path = Some("my_wallet.json".to_owned()); + conf.arg_password = vec!["pwd".into()]; + + let conf = Configuration { + args: conf, + }; + + let conf: Cmd = conf.into_command().unwrap().cmd; + + let cmd_arg = Cmd::ImportPresaleWallet(ImportWallet { + iterations: 10240, + path: Directories::default().keys, + wallet_path: "my_wallet.json".into(), + password_file: Some("pwd".into()), + spec: SpecType::default(), + }); + + assert_eq!(conf, cmd_arg); + } + + #[test] + fn test_command_blockchain_import() { + + let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + conf.cmd_import = true; + conf.arg_import_file = Some("blockchain.json".to_owned()); + + let conf = Configuration { + args: conf, + }; + + let conf: Cmd = conf.into_command().unwrap().cmd; + + let cmd_arg = Cmd::Blockchain(BlockchainCmd::Import(ImportBlockchain { + spec: Default::default(), + cache_config: Default::default(), + dirs: Default::default(), + file_path: Some("blockchain.json".into()), + format: Default::default(), + pruning: Default::default(), + pruning_history: 128, + pruning_memory: 64, + compaction: Default::default(), + tracing: Default::default(), + fat_db: Default::default(), + check_seal: true, + with_color: !cfg!(windows), + verifier_settings: Default::default(), + light: false, + max_round_blocks_to_import: 12, + })); + + assert_eq!(conf, cmd_arg); + } + + #[test] + fn test_command_blockchain_export() { + let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + conf.cmd_export = true; + conf.cmd_export_blocks = true; + conf.arg_export_blocks_from = "1".to_owned(); + conf.arg_export_blocks_to = "latest".to_owned(); + conf.arg_export_blocks_file = Some("blockchain.json".to_owned()); + + let conf = Configuration { + args: conf, + }; + + let conf: Cmd = conf.into_command().unwrap().cmd; + + let cmd_arg = Cmd::Blockchain(BlockchainCmd::Export(ExportBlockchain { + spec: Default::default(), + cache_config: Default::default(), + dirs: Default::default(), + file_path: Some("blockchain.json".into()), + pruning: Default::default(), + pruning_history: 128, + pruning_memory: 64, + format: Default::default(), + compaction: Default::default(), + tracing: Default::default(), + fat_db: Default::default(), + from_block: BlockId::Number(1), + to_block: BlockId::Latest, + check_seal: true, + max_round_blocks_to_import: 12, + })); + assert_eq!(conf, cmd_arg); + } + #[test] + fn test_command_state_export() { + let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + conf.cmd_export = true; + conf.cmd_export_state = true; + conf.arg_export_state_at = "latest".to_owned(); + conf.arg_export_state_min_balance = None; + conf.arg_export_state_max_balance = None; + conf.arg_export_state_file = Some("state.json".to_owned()); + + let conf = Configuration { + args: conf, + }; + + let conf: Cmd = conf.into_command().unwrap().cmd; + + let cmd_arg = Cmd::Blockchain(BlockchainCmd::ExportState(ExportState { + spec: Default::default(), + cache_config: Default::default(), + dirs: Default::default(), + file_path: Some("state.json".into()), + pruning: Default::default(), + pruning_history: 128, + pruning_memory: 64, + format: Default::default(), + compaction: Default::default(), + tracing: Default::default(), + fat_db: Default::default(), + at: BlockId::Latest, + storage: true, + code: true, + min_balance: None, + max_balance: None, + max_round_blocks_to_import: 12, + })); + + assert_eq!(conf, cmd_arg); + } + + #[test] + fn test_command_blockchain_export_with_custom_format() { + + let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + conf.cmd_export = true; + conf.cmd_export_blocks = true; + conf.arg_export_blocks_from = "1".to_owned(); + conf.arg_export_blocks_to = "latest".to_owned(); + conf.arg_export_blocks_format = Some("hex".to_owned()); + conf.arg_export_blocks_file = Some("blockchain.json".to_owned()); + + let conf = Configuration { + args: conf, + }; + + let conf: Cmd = conf.into_command().unwrap().cmd; + + let cmd_arg = Cmd::Blockchain(BlockchainCmd::Export(ExportBlockchain { + spec: Default::default(), + cache_config: Default::default(), + dirs: Default::default(), + file_path: Some("blockchain.json".into()), + pruning: Default::default(), + pruning_history: 128, + pruning_memory: 64, + format: Some(DataFormat::Hex), + compaction: Default::default(), + tracing: Default::default(), + fat_db: Default::default(), + from_block: BlockId::Number(1), + to_block: BlockId::Latest, + check_seal: true, + max_round_blocks_to_import: 12, + })); + assert_eq!(conf, cmd_arg); + } + #[test] + fn test_command_signer_new_token() { + + let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + conf.cmd_signer = true; + conf.cmd_signer_new_token = true; + + let conf = Configuration { + args: conf, + }; + + let conf: Cmd = conf.into_command().unwrap().cmd; + + let expected = Directories::default().signer; + let cmd_arg = Cmd::SignerToken(WsConfiguration { + enabled: true, + interface: "127.0.0.1".into(), + port: 8546, + apis: ApiSet::UnsafeContext, + origins: Some(vec!["parity://*".into(),"chrome-extension://*".into(), "moz-extension://*".into()]), + hosts: Some(vec![]), + signer_path: expected.into(), + support_token_api: false, + max_connections: 100, + }, LogConfig { + color: !cfg!(windows), + mode: None, + file: None, + } ); + + assert_eq!(conf, cmd_arg); + } + + #[test] + fn test_ws_max_connections() { + let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + conf.arg_ws_max_connections = 1; + + let conf = Configuration { + args: conf, + }; + + assert_eq!(conf.ws_config().unwrap(), WsConfiguration { + max_connections: 1, + ..Default::default() + }); + } + + #[test] + fn test_run_cmd() { + let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + let conf = Configuration { + args: conf, + }; + + let conf = conf.into_command().unwrap().cmd; + + let mut expected = RunCmd { + allow_missing_blocks: false, + cache_config: Default::default(), + dirs: Default::default(), + spec: Default::default(), + pruning: Default::default(), + pruning_history: 128, + pruning_memory: 64, + daemon: None, + logger_config: Default::default(), + miner_options: Default::default(), + gas_price_percentile: 50, + poll_lifetime: 60, + ws_conf: Default::default(), + http_conf: Default::default(), + ipc_conf: Default::default(), + net_conf: default_network_config(), + network_id: None, + warp_sync: true, + warp_barrier: None, + acc_conf: Default::default(), + gas_pricer_conf: Default::default(), + miner_extras: Default::default(), + update_policy: UpdatePolicy { + enable_downloading: true, + require_consensus: true, + filter: UpdateFilter::Critical, + track: ReleaseTrack::Unknown, + path: default_hypervisor_path(), + max_size: 128 * 1024 * 1024, + max_delay: 100, + frequency: 20, + }, + mode: Default::default(), + tracing: Default::default(), + compaction: Default::default(), + geth_compatibility: false, + experimental_rpcs: false, + net_settings: Default::default(), + secretstore_conf: Default::default(), + private_provider_conf: Default::default(), + private_encryptor_conf: Default::default(), + private_tx_enabled: false, + name: "".into(), + custom_bootnodes: false, + fat_db: Default::default(), + snapshot_conf: Default::default(), + stratum: None, + check_seal: true, + download_old_blocks: true, + verifier_settings: Default::default(), + serve_light: true, + light: false, + no_hardcoded_sync: false, + no_persistent_txqueue: false, + max_round_blocks_to_import: 12, + on_demand_response_time_window: None, + on_demand_request_backoff_start: None, + on_demand_request_backoff_max: None, + on_demand_request_backoff_rounds_max: None, + on_demand_request_consecutive_failures: None, + sync_until: None, + }; + expected.secretstore_conf.enabled = cfg!(feature = "secretstore"); + expected.secretstore_conf.http_enabled = cfg!(feature = "secretstore"); + + assert_eq!(conf, Cmd::Run(expected)); + } + + #[test] + fn should_parse_mining_options() { + // given + let mut mining_options = MinerOptions::default(); + + // setting up 2 separate configs + let (mut conf0, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf0.absorb_cli(raw, user_defaults, fallback).unwrap(); // default config + + let mut conf2 = conf0.clone(); + conf2.arg_tx_queue_strategy = "gas_price".to_owned(); // modified config + + let conf0 = Configuration { + args: conf0, + }; + + let conf2 = Configuration { + args: conf2, + }; + + // then + assert_eq!(conf0.miner_options().unwrap(), mining_options); + mining_options.tx_queue_strategy = PrioritizationStrategy::GasPriceOnly; + assert_eq!(conf2.miner_options().unwrap(), mining_options); + } + + #[test] + fn should_fail_on_force_reseal_and_reseal_min_period() { + let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + conf.arg_chain = "dev".to_owned(); + conf.flag_force_sealing = true; + conf.arg_reseal_min_period = 0; + + let conf = Configuration { + args: conf, + }; + + assert!(conf.miner_options().is_err()); + } + + #[test] + fn should_parse_updater_options() { + let (mut conf0, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf0.absorb_cli(raw, user_defaults, fallback).unwrap(); + + conf0.arg_auto_update = "all".to_owned(); + conf0.arg_auto_update_delay = 300; + conf0.flag_no_consensus = true; + + let conf0 = Configuration { + args: conf0, + }; + + assert_eq!(conf0.update_policy().unwrap(), UpdatePolicy { + enable_downloading: true, + require_consensus: false, + filter: UpdateFilter::All, + track: ReleaseTrack::Unknown, + path: default_hypervisor_path(), + max_size: 128 * 1024 * 1024, + max_delay: 300, + frequency: 20, + }); + } + + #[test] + fn should_parse_network_settings() { + let (mut conf0, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf0.absorb_cli(raw, user_defaults, fallback).unwrap(); + + conf0.arg_identity = "testname".to_owned(); + conf0.arg_chain = "goerli".to_owned(); + + let conf0 = Configuration { + args: conf0, + }; + + // then + assert_eq!(conf0.network_settings(), Ok(NetworkSettings { + name: "testname".to_owned(), + chain: "goerli".to_owned(), + is_dev_chain: false, + network_port: 30303, + rpc_enabled: true, + rpc_interface: "127.0.0.1".to_owned(), + rpc_port: 8545, + })); + } + + #[test] + fn should_parse_rpc_settings_with_geth_compatiblity() { + // given + fn assert(conf: Configuration) { + let net = conf.network_settings().unwrap(); + assert_eq!(net.rpc_enabled, true); + assert_eq!(net.rpc_interface, "0.0.0.0".to_owned()); + assert_eq!(net.rpc_port, 8000); + assert_eq!(conf.rpc_cors(), None); + assert_eq!(conf.rpc_apis(), "web3,eth".to_owned()); + } + + let (mut conf0, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf0.absorb_cli(raw, user_defaults, fallback).unwrap(); + + let conf2 = conf0.clone(); + + conf0.arg_jsonrpc_port = 8000; + conf0.arg_jsonrpc_interface = "all".to_owned(); + conf0.arg_jsonrpc_cors = "*".to_owned(); + conf0.arg_jsonrpc_apis = "web3,eth".to_owned(); + + let conf0 = Configuration { + args: conf0, + }; + assert(conf0); + } + + #[test] + fn should_parse_rpc_hosts() { + // given + let (mut conf0, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf0.absorb_cli(raw, user_defaults, fallback).unwrap(); + + let mut conf1 = conf0.clone(); + let mut conf2 = conf0.clone(); + let mut conf3 = conf0.clone(); + + conf1.arg_jsonrpc_hosts = "none".to_owned(); + conf2.arg_jsonrpc_hosts = "all".to_owned(); + conf3.arg_jsonrpc_hosts = "parity.io,something.io".to_owned(); + + let conf0 = Configuration { + args: conf0, + }; + + let conf1 = Configuration { + args: conf1, + }; + let conf2 = Configuration { + args: conf2, + }; + let conf3 = Configuration { + args: conf3, + }; + // then + assert_eq!(conf0.rpc_hosts(), Some(Vec::new())); + assert_eq!(conf1.rpc_hosts(), Some(Vec::new())); + assert_eq!(conf2.rpc_hosts(), None); + assert_eq!(conf3.rpc_hosts(), Some(vec!["parity.io".into(), "something.io".into()])); + } + + #[test] + fn should_respect_only_min_peers_and_default() { + let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + conf.arg_min_peers = Some(5); + + let conf = Configuration{ + args: conf, + }; + + match conf.into_command().unwrap().cmd { + Cmd::Run(c) => { + assert_eq!(c.net_conf.min_peers, 5); + assert_eq!(c.net_conf.max_peers, 50); + }, + _ => panic!("Should be Cmd::Run"), + } + } + + #[test] + fn should_respect_only_min_peers_and_greater_than_default() { + let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + conf.arg_min_peers = Some(500); + + let conf = Configuration{ + args: conf, + }; + + match conf.into_command().unwrap().cmd { + Cmd::Run(c) => { + assert_eq!(c.net_conf.min_peers, 500); + assert_eq!(c.net_conf.max_peers, 500); + }, + _ => panic!("Should be Cmd::Run"), + } + } + + #[test] + fn should_parse_secretstore_cors() { + let (mut conf0, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf0.absorb_cli(raw, user_defaults, fallback).unwrap(); + + let mut conf1 = conf0.clone(); + let mut conf2 = conf0.clone(); + + conf1.arg_secretstore_http_cors = "*".to_owned(); + conf2.arg_secretstore_http_cors = "http://parity.io,http://something.io".to_owned(); + + let conf0 = Configuration{ + args: conf0, + }; + + let conf1 = Configuration{ + args: conf1, + }; + + let conf2 = Configuration{ + args: conf2, + }; + + // then + assert_eq!(conf0.secretstore_cors(), Some(vec![])); + assert_eq!(conf1.secretstore_cors(), None); + assert_eq!(conf2.secretstore_cors(), Some(vec!["http://parity.io".into(),"http://something.io".into()])); + } + + #[test] + fn ensures_sane_http_settings() { + let (mut conf0, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf0.absorb_cli(raw, user_defaults, fallback).unwrap(); + + conf0.arg_jsonrpc_server_threads = Some(0); + conf0.arg_jsonrpc_max_payload = Some(0); + + let conf0 = Configuration { + args: conf0, + }; + + // then things are adjusted to Just Work. + let http_conf = conf0.http_config().unwrap(); + assert_eq!(http_conf.server_threads, 1); + assert_eq!(http_conf.max_payload, 1); + } + + #[test] + fn jsonrpc_threading_defaults() { + + let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + assert_eq!(conf.arg_jsonrpc_server_threads, Some(4)); + } + + #[test] + fn test_dev_preset() { + + let raw: ArgsInput = Default::default(); + let mut conf: Args = Default::default(); + + let (user_defaults, fallback) = Args::generate_default_configuration( + "config_dev.toml", + "config_default.toml" + ).unwrap(); + + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + let conf = Configuration { + args: conf, + }; + + match conf.into_command().unwrap().cmd { + Cmd::Run(c) => { + assert_eq!(c.net_settings.chain, "dev"); + assert_eq!(c.gas_pricer_conf, GasPricerConfig::Fixed(0.into())); + assert_eq!(c.miner_options.reseal_min_period, Duration::from_millis(0)); + }, + _ => panic!("Should be Cmd::Run"), + } + } + + #[test] + fn test_mining_preset() { + + let raw: ArgsInput = Default::default(); + let mut conf: Args = Default::default(); + + let (user_defaults, fallback) = Args::generate_default_configuration( + "config_mining.toml", + "config_default.toml" + ).unwrap(); + + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + let conf = Configuration { + args: conf, + }; + + match conf.into_command().unwrap().cmd { + Cmd::Run(c) => { + assert_eq!(c.net_conf.min_peers, 50); + assert_eq!(c.net_conf.max_peers, 100); + assert_eq!(c.ipc_conf.enabled, false); + assert_eq!(c.miner_options.force_sealing, true); + assert_eq!(c.miner_options.reseal_on_external_tx, true); + assert_eq!(c.miner_options.reseal_on_own_tx, true); + assert_eq!(c.miner_options.reseal_min_period, Duration::from_millis(4000)); + assert_eq!(c.miner_options.pool_limits.max_count, 8192); + assert_eq!(c.cache_config, CacheConfig::new_with_total_cache_size(1024)); + assert_eq!(c.logger_config.mode.unwrap(), "miner=trace,own_tx=trace"); + }, + _ => panic!("Should be Cmd::Run"), + } + } + + #[test] + fn test_non_standard_ports_preset() { + let raw: ArgsInput = Default::default(); + let mut conf: Args = Default::default(); + + let (user_defaults, fallback) = Args::generate_default_configuration( + "config_non_standard_ports.toml", + "config_default.toml" + ).unwrap(); + + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + let conf = Configuration { + args: conf, + }; + + match conf.into_command().unwrap().cmd { + Cmd::Run(c) => { + assert_eq!(c.net_settings.network_port, 30305); + assert_eq!(c.net_settings.rpc_port, 8645); + }, + _ => panic!("Should be Cmd::Run"), + } + } + + #[test] + fn test_insecure_preset() { + + let raw: ArgsInput = Default::default(); + let mut conf: Args = Default::default(); + + let (user_defaults, fallback) = Args::generate_default_configuration( + "config_insecure.toml", + "config_default.toml" + ).unwrap(); + + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + let conf = Configuration { + args: conf, + }; + + match conf.into_command().unwrap().cmd { + Cmd::Run(c) => { + assert_eq!(c.update_policy.require_consensus, false); + assert_eq!(c.net_settings.rpc_interface, "0.0.0.0"); + match c.http_conf.apis { + ApiSet::List(set) => assert_eq!(set, ApiSet::All.list_apis()), + _ => panic!("Incorrect rpc apis"), + } +; + assert_eq!(c.http_conf.hosts, None); + }, + _ => panic!("Should be Cmd::Run"), + } + } + + #[test] + fn test_dev_insecure_preset() { + + let raw: ArgsInput = Default::default(); + let mut conf: Args = Default::default(); + + let (user_defaults, fallback) = Args::generate_default_configuration( + "config_dev_insecure.toml", + "config_default.toml" + ).unwrap(); + + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + let conf = Configuration { + args: conf, + }; + + match conf.into_command().unwrap().cmd { + Cmd::Run(c) => { + assert_eq!(c.net_settings.chain, "dev"); + assert_eq!(c.gas_pricer_conf, GasPricerConfig::Fixed(0.into())); + assert_eq!(c.miner_options.reseal_min_period, Duration::from_millis(0)); + assert_eq!(c.update_policy.require_consensus, false); + assert_eq!(c.net_settings.rpc_interface, "0.0.0.0"); + match c.http_conf.apis { + ApiSet::List(set) => assert_eq!(set, ApiSet::All.list_apis()), + _ => panic!("Incorrect rpc apis"), + } + // "web3,eth,net,personal,parity,parity_set,traces,rpc,parity_accounts"); + assert_eq!(c.http_conf.hosts, None); + }, + _ => panic!("Should be Cmd::Run"), + } + } + + #[test] + fn test_override_preset() { + + let mut raw: ArgsInput = Default::default(); + let mut conf: Args = Default::default(); + + raw.globals.networking.min_peers = Some(99); + + let (user_defaults, fallback) = Args::generate_default_configuration( + "config_mining.toml", + "config_default.toml" + ).unwrap(); + + conf.absorb_cli(raw, user_defaults, fallback).unwrap(); + + let conf = Configuration { + args: conf, + }; + + match conf.into_command().unwrap().cmd { + Cmd::Run(c) => { + assert_eq!(c.net_conf.min_peers, 99); + }, + _ => panic!("Should be Cmd::Run"), + } + } + + #[test] + fn test_identity_arg() { + let (mut conf0, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf0.absorb_cli(raw, user_defaults, fallback).unwrap(); + + conf0.arg_identity = "Somebody".to_owned(); + + let conf0 = Configuration { + args: conf0 + }; + + match conf0.into_command().unwrap().cmd { + Cmd::Run(c) => { + assert_eq!(c.name, "Somebody"); + assert!(c.net_conf.client_version.starts_with("OpenEthereum/Somebody/")); + } + _ => panic!("Should be Cmd::Run"), + } + } + + #[test] + fn should_apply_ports_shift() { + // give + let (mut conf0, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf0.absorb_cli(raw, user_defaults, fallback).unwrap(); + + let mut conf1 = conf0.clone(); + + conf0.arg_ports_shift = 1; + conf0.flag_stratum = true; + + conf1.arg_ports_shift = 1; + conf1.arg_jsonrpc_port = 8544; + + let conf0 = Configuration { + args: conf0 + }; + + let conf1 = Configuration { + args: conf1 + }; + + assert_eq!(conf0.net_addresses().unwrap().0.port(), 30304); + assert_eq!(conf0.network_settings().unwrap().network_port, 30304); + assert_eq!(conf0.network_settings().unwrap().rpc_port, 8546); + assert_eq!(conf0.http_config().unwrap().port, 8546); + assert_eq!(conf0.ws_config().unwrap().port, 8547); + assert_eq!(conf0.secretstore_config().unwrap().port, 8084); + assert_eq!(conf0.secretstore_config().unwrap().http_port, 8083); + assert_eq!(conf0.stratum_options().unwrap().unwrap().port, 8009); + + assert_eq!(conf1.net_addresses().unwrap().0.port(), 30304); + assert_eq!(conf1.network_settings().unwrap().network_port, 30304); + assert_eq!(conf1.network_settings().unwrap().rpc_port, 8545); + assert_eq!(conf1.http_config().unwrap().port, 8545); + assert_eq!(conf1.ws_config().unwrap().port, 8547); + assert_eq!(conf1.secretstore_config().unwrap().port, 8084); + assert_eq!(conf1.secretstore_config().unwrap().http_port, 8083); + } + + #[test] + fn should_resolve_external_nat_hosts() { + + let (mut conf0, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf0.absorb_cli(raw, user_defaults, fallback).unwrap(); + + let mut conf1 = conf0.clone(); + let mut conf2 = conf0.clone(); + let mut conf3 = conf0.clone(); + let mut conf4 = conf0.clone(); + + conf0.arg_nat = "extip:1.1.1.1".to_owned(); + + let conf0 = Configuration { + args: conf0 + }; + + conf1.arg_nat = "extip:192.168.1.1:123".to_owned(); + let conf1 = Configuration { + args: conf1 + }; + + conf2.arg_nat = "extip:ethereum.org".to_owned(); + let conf2 = Configuration { + args: conf2 + }; + + conf3.arg_nat = "extip:ethereum.org:whatever bla bla 123".to_owned(); + let conf3 = Configuration { + args: conf3 + }; + + conf4.arg_nat = "extip:blabla".to_owned(); + let conf4 = Configuration { + args: conf4 + }; + // Ip works + assert_eq!(conf0.net_addresses().unwrap().1.unwrap().ip().to_string(), "1.1.1.1"); + assert_eq!(conf0.net_addresses().unwrap().1.unwrap().port(), 30303); + + // Ip with port works, port is discarded + assert_eq!(conf1.net_addresses().unwrap().1.unwrap().ip().to_string(), "192.168.1.1"); + assert_eq!(conf1.net_addresses().unwrap().1.unwrap().port(), 30303); + + // Hostname works + assert!(conf2.net_addresses().unwrap().1.is_some()); + assert_eq!(conf2.net_addresses().unwrap().1.unwrap().port(), 30303); + + // Hostname works, garbage at the end is discarded + assert!(conf3.net_addresses().unwrap().1.is_some()); + assert_eq!(conf3.net_addresses().unwrap().1.unwrap().port(), 30303); + + // Garbage is error + assert!(conf4.net_addresses().is_err()); + } + + #[test] + fn should_expose_all_servers() { + let (mut conf0, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf0.absorb_cli(raw, user_defaults, fallback).unwrap(); + + conf0.flag_unsafe_expose = true; + + let conf0 = Configuration { + args: conf0 + }; + + assert_eq!(&conf0.network_settings().unwrap().rpc_interface, "0.0.0.0"); + assert_eq!(&conf0.http_config().unwrap().interface, "0.0.0.0"); + assert_eq!(conf0.http_config().unwrap().hosts, None); + assert_eq!(&conf0.ws_config().unwrap().interface, "0.0.0.0"); + assert_eq!(conf0.ws_config().unwrap().hosts, None); + assert_eq!(conf0.ws_config().unwrap().origins, None); + assert_eq!(&conf0.secretstore_config().unwrap().interface, "0.0.0.0"); + assert_eq!(&conf0.secretstore_config().unwrap().http_interface, "0.0.0.0"); + } + + #[test] + fn allow_ips() { + + let (mut all, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + all.absorb_cli(raw, user_defaults, fallback).unwrap(); + + let mut private = all.clone(); + let mut block_custom = all.clone(); + let mut combo = all.clone(); + let mut ipv6_custom_public = all.clone(); + let mut ipv6_custom_private = all.clone(); + + all.arg_allow_ips = "all".to_owned(); + let all = Configuration { + args: all + }; + + private.arg_allow_ips = "private".to_owned(); + let private = Configuration { + args: private + }; + + block_custom.arg_allow_ips = "-10.0.0.0/8".to_owned(); + let block_custom = Configuration { + args: block_custom + }; + + combo.arg_allow_ips = "public 10.0.0.0/8 -1.0.0.0/8".to_owned(); + let combo = Configuration { + args: combo + }; + + ipv6_custom_public.arg_allow_ips = "public fc00::/7".to_owned(); + let ipv6_custom_public = Configuration { + args: ipv6_custom_public + }; + + ipv6_custom_private.arg_allow_ips = "private -fc00::/7".to_owned(); + let ipv6_custom_private = Configuration { + args: ipv6_custom_private + }; + + assert_eq!(all.ip_filter().unwrap(), IpFilter { + predefined: AllowIP::All, + custom_allow: vec![], + custom_block: vec![], + }); + + assert_eq!(private.ip_filter().unwrap(), IpFilter { + predefined: AllowIP::Private, + custom_allow: vec![], + custom_block: vec![], + }); + + assert_eq!(block_custom.ip_filter().unwrap(), IpFilter { + predefined: AllowIP::All, + custom_allow: vec![], + custom_block: vec![IpNetwork::from_str("10.0.0.0/8").unwrap()], + }); + + assert_eq!(combo.ip_filter().unwrap(), IpFilter { + predefined: AllowIP::Public, + custom_allow: vec![IpNetwork::from_str("10.0.0.0/8").unwrap()], + custom_block: vec![IpNetwork::from_str("1.0.0.0/8").unwrap()], + }); + + assert_eq!(ipv6_custom_public.ip_filter().unwrap(), IpFilter { + predefined: AllowIP::Public, + custom_allow: vec![IpNetwork::from_str("fc00::/7").unwrap()], + custom_block: vec![], + }); + + assert_eq!(ipv6_custom_private.ip_filter().unwrap(), IpFilter { + predefined: AllowIP::Private, + custom_allow: vec![], + custom_block: vec![IpNetwork::from_str("fc00::/7").unwrap()], + }); + } + + #[test] + fn should_use_correct_cache_path_if_base_is_set() { + use std::path; + + let (mut std, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + std.absorb_cli(raw, user_defaults, fallback).unwrap(); + + let mut base = std.clone(); + base.arg_base_path = Some("/test".to_owned()); + + let std = Configuration { + args: std + }; + + let base = Configuration { + args: base + }; + + let base_path = ::dir::default_data_path(); + let local_path = ::dir::default_local_path(); + assert_eq!(std.directories().cache, dir::helpers::replace_home_and_local(&base_path, &local_path, ::dir::CACHE_PATH)); + assert_eq!(path::Path::new(&base.directories().cache), path::Path::new("/test/cache")); + } + + #[test] + fn should_respect_only_max_peers_and_default() { + + let (mut conf0, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf0.absorb_cli(raw, user_defaults, fallback).unwrap(); + + conf0.arg_max_peers = Some(50); + + let conf0 = Configuration { + args: conf0 + }; + + match conf0.into_command().unwrap().cmd { + Cmd::Run(c) => { + assert_eq!(c.net_conf.min_peers, 25); + assert_eq!(c.net_conf.max_peers, 50); + }, + _ => panic!("Should be Cmd::Run"), + } + } + + #[test] + fn should_respect_only_max_peers_less_than_default() { + let (mut conf0, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); + conf0.absorb_cli(raw, user_defaults, fallback).unwrap(); + + conf0.arg_max_peers = Some(5); + + let conf0 = Configuration { + args: conf0 + }; + + match conf0.into_command().unwrap().cmd { + Cmd::Run(c) => { + assert_eq!(c.net_conf.min_peers, 5); + assert_eq!(c.net_conf.max_peers, 5); + }, + _ => panic!("Should be Cmd::Run"), + } + } + +} diff --git a/parity/lib.rs b/parity/lib.rs index fb7d4d1cb82..ff08d458105 100644 --- a/parity/lib.rs +++ b/parity/lib.rs @@ -21,7 +21,6 @@ extern crate ansi_term; extern crate docopt; extern crate rust_embed; extern crate clap; -extern crate structopt; extern crate dir; extern crate futures; extern crate atty; @@ -104,7 +103,6 @@ mod blockchain; mod cache; mod cli; mod configuration; -mod test_configuration; mod export_hardcoded_sync; mod helpers; mod informant; @@ -205,7 +203,7 @@ fn execute( Ok(ExecutionAction::Running(outcome)) }, - // NOTE: this is handled automatically by structopt + // NOTE: this is handled automatically by Clap // Cmd::Version => Ok(ExecutionAction::Instant(Some(Args::print_version()))), Cmd::Hash(maybe_file) => print_hash_of(maybe_file).map(|s| ExecutionAction::Instant(Some(s))), Cmd::Account(account_cmd) => account::execute(account_cmd).map(|s| ExecutionAction::Instant(Some(s))), diff --git a/parity/test_configuration.rs b/parity/test_configuration.rs deleted file mode 100644 index 96dd309160d..00000000000 --- a/parity/test_configuration.rs +++ /dev/null @@ -1,1147 +0,0 @@ -#[cfg(test)] -mod test_configuration{ - use cli::args::Args; - use cli::parse_cli::ArgsInput; - use cli::globals::Globals; - use ethcore_logger::Config as LogConfig; - use configuration::{Configuration, Cmd}; - use std::time::Duration; - use params::{GasPricerConfig}; - use cache::CacheConfig; - - use std::io::Write; - use std::fs::File; - use std::str::FromStr; - - use tempfile::TempDir; - use ethcore::miner::MinerOptions; - use miner::pool::PrioritizationStrategy; - use parity_rpc::NetworkSettings; - use updater::{UpdatePolicy, UpdateFilter, ReleaseTrack}; - use types::ids::BlockId; - use types::data_format::DataFormat; - use account::{AccountCmd, NewAccount, ImportAccounts, ListAccounts}; - use blockchain::{BlockchainCmd, ImportBlockchain, ExportBlockchain, ExportState}; - use dir::{Directories, default_hypervisor_path}; - use helpers::{default_network_config}; - use params::SpecType; - use presale::ImportWallet; - use rpc::WsConfiguration; - use rpc_apis::ApiSet; - use run::RunCmd; - - use network::{AllowIP, IpFilter}; - - extern crate ipnetwork; - use self::ipnetwork::IpNetwork; - - use super::*; - - - fn intialize_with_out_of_the_box_defaults() -> (Args, ArgsInput, Globals, Globals) { - let raw: ArgsInput = Default::default(); - let resolved: Args = Default::default(); - let (user_defaults, fallback) = Args::generate_default_configuration( - "config_default.toml", - "config_default.toml" - ).unwrap(); - - (resolved, raw, user_defaults, fallback) - } - - #[test] - fn test_subcommand_account_new() { - let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); - conf.absorb_cli(raw, user_defaults, fallback).unwrap(); - - conf.cmd_account = true; - conf.cmd_account_new = true; - - let conf = Configuration { - args: conf, - }; - - let conf: Cmd = conf.into_command().unwrap().cmd; - - let cmd_arg: Cmd = Cmd::Account( - AccountCmd::New(NewAccount{ - iterations: 10240, - path: Directories::default().keys, - password_file: None, - spec: SpecType::default(), - })); - - assert_eq!(conf, cmd_arg); - - } - - #[test] - fn test_command_account_list() { - let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); - - conf.cmd_account = true; - conf.cmd_account_list = true; - conf.absorb_cli(raw, user_defaults, fallback).unwrap(); - - let conf = Configuration { - args: conf, - }; - - let conf: Cmd = conf.into_command().unwrap().cmd; - - let cmd_arg: Cmd = Cmd::Account( - AccountCmd::List(ListAccounts { - path: Directories::default().keys, - spec: SpecType::default(), - })); - - assert_eq!(conf, cmd_arg); - - } - - #[test] - fn test_command_account_import() { - - let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); - conf.absorb_cli(raw, user_defaults, fallback).unwrap(); - - conf.cmd_account = true; - conf.cmd_account_import = true; - conf.arg_account_import_path = Some(vec!["my_dir".into(), "another_dir".into()]); - - let conf = Configuration { - args: conf, - }; - - let conf: Cmd = conf.into_command().unwrap().cmd; - - let cmd_arg: Cmd = Cmd::Account(AccountCmd::Import(ImportAccounts { - from: vec!["my_dir".into(), "another_dir".into()], - to: Directories::default().keys, - spec: SpecType::default(), - })); - - assert_eq!(conf, cmd_arg); - } - - #[test] - fn test_command_wallet_import() { - let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); - conf.absorb_cli(raw, user_defaults, fallback).unwrap(); - - conf.cmd_wallet = true; - conf.cmd_wallet_import = true; - conf.arg_wallet_import_path = Some("my_wallet.json".to_owned()); - conf.arg_password = vec!["pwd".into()]; - - let conf = Configuration { - args: conf, - }; - - let conf: Cmd = conf.into_command().unwrap().cmd; - - let cmd_arg = Cmd::ImportPresaleWallet(ImportWallet { - iterations: 10240, - path: Directories::default().keys, - wallet_path: "my_wallet.json".into(), - password_file: Some("pwd".into()), - spec: SpecType::default(), - }); - - assert_eq!(conf, cmd_arg); - } - - #[test] - fn test_command_blockchain_import() { - - let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); - conf.absorb_cli(raw, user_defaults, fallback).unwrap(); - - conf.cmd_import = true; - conf.arg_import_file = Some("blockchain.json".to_owned()); - - let conf = Configuration { - args: conf, - }; - - let conf: Cmd = conf.into_command().unwrap().cmd; - - let cmd_arg = Cmd::Blockchain(BlockchainCmd::Import(ImportBlockchain { - spec: Default::default(), - cache_config: Default::default(), - dirs: Default::default(), - file_path: Some("blockchain.json".into()), - format: Default::default(), - pruning: Default::default(), - pruning_history: 128, - pruning_memory: 64, - compaction: Default::default(), - tracing: Default::default(), - fat_db: Default::default(), - check_seal: true, - with_color: !cfg!(windows), - verifier_settings: Default::default(), - light: false, - max_round_blocks_to_import: 12, - })); - - assert_eq!(conf, cmd_arg); - } - - #[test] - fn test_command_blockchain_export() { - let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); - conf.absorb_cli(raw, user_defaults, fallback).unwrap(); - - conf.cmd_export = true; - conf.cmd_export_blocks = true; - conf.arg_export_blocks_from = "1".to_owned(); - conf.arg_export_blocks_to = "latest".to_owned(); - conf.arg_export_blocks_file = Some("blockchain.json".to_owned()); - - let conf = Configuration { - args: conf, - }; - - let conf: Cmd = conf.into_command().unwrap().cmd; - - let cmd_arg = Cmd::Blockchain(BlockchainCmd::Export(ExportBlockchain { - spec: Default::default(), - cache_config: Default::default(), - dirs: Default::default(), - file_path: Some("blockchain.json".into()), - pruning: Default::default(), - pruning_history: 128, - pruning_memory: 64, - format: Default::default(), - compaction: Default::default(), - tracing: Default::default(), - fat_db: Default::default(), - from_block: BlockId::Number(1), - to_block: BlockId::Latest, - check_seal: true, - max_round_blocks_to_import: 12, - })); - assert_eq!(conf, cmd_arg); - } - #[test] - fn test_command_state_export() { - let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); - conf.absorb_cli(raw, user_defaults, fallback).unwrap(); - - conf.cmd_export = true; - conf.cmd_export_state = true; - conf.arg_export_state_at = "latest".to_owned(); - conf.arg_export_state_min_balance = None; - conf.arg_export_state_max_balance = None; - conf.arg_export_state_file = Some("state.json".to_owned()); - - let conf = Configuration { - args: conf, - }; - - let conf: Cmd = conf.into_command().unwrap().cmd; - - let cmd_arg = Cmd::Blockchain(BlockchainCmd::ExportState(ExportState { - spec: Default::default(), - cache_config: Default::default(), - dirs: Default::default(), - file_path: Some("state.json".into()), - pruning: Default::default(), - pruning_history: 128, - pruning_memory: 64, - format: Default::default(), - compaction: Default::default(), - tracing: Default::default(), - fat_db: Default::default(), - at: BlockId::Latest, - storage: true, - code: true, - min_balance: None, - max_balance: None, - max_round_blocks_to_import: 12, - })); - - assert_eq!(conf, cmd_arg); - } - - #[test] - fn test_command_blockchain_export_with_custom_format() { - - let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); - conf.absorb_cli(raw, user_defaults, fallback).unwrap(); - - conf.cmd_export = true; - conf.cmd_export_blocks = true; - conf.arg_export_blocks_from = "1".to_owned(); - conf.arg_export_blocks_to = "latest".to_owned(); - conf.arg_export_blocks_format = Some("hex".to_owned()); - conf.arg_export_blocks_file = Some("blockchain.json".to_owned()); - - let conf = Configuration { - args: conf, - }; - - let conf: Cmd = conf.into_command().unwrap().cmd; - - let cmd_arg = Cmd::Blockchain(BlockchainCmd::Export(ExportBlockchain { - spec: Default::default(), - cache_config: Default::default(), - dirs: Default::default(), - file_path: Some("blockchain.json".into()), - pruning: Default::default(), - pruning_history: 128, - pruning_memory: 64, - format: Some(DataFormat::Hex), - compaction: Default::default(), - tracing: Default::default(), - fat_db: Default::default(), - from_block: BlockId::Number(1), - to_block: BlockId::Latest, - check_seal: true, - max_round_blocks_to_import: 12, - })); - assert_eq!(conf, cmd_arg); - } - #[test] - fn test_command_signer_new_token() { - - let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); - conf.absorb_cli(raw, user_defaults, fallback).unwrap(); - - conf.cmd_signer = true; - conf.cmd_signer_new_token = true; - - let conf = Configuration { - args: conf, - }; - - let conf: Cmd = conf.into_command().unwrap().cmd; - - let expected = Directories::default().signer; - let cmd_arg = Cmd::SignerToken(WsConfiguration { - enabled: true, - interface: "127.0.0.1".into(), - port: 8546, - apis: ApiSet::UnsafeContext, - origins: Some(vec!["parity://*".into(),"chrome-extension://*".into(), "moz-extension://*".into()]), - hosts: Some(vec![]), - signer_path: expected.into(), - support_token_api: false, - max_connections: 100, - }, LogConfig { - color: !cfg!(windows), - mode: None, - file: None, - } ); - - assert_eq!(conf, cmd_arg); - } - - #[test] - fn test_ws_max_connections() { - let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); - conf.absorb_cli(raw, user_defaults, fallback).unwrap(); - - conf.arg_ws_max_connections = 1; - - let conf = Configuration { - args: conf, - }; - - assert_eq!(conf.ws_config().unwrap(), WsConfiguration { - max_connections: 1, - ..Default::default() - }); - } - - #[test] - fn test_run_cmd() { - let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); - conf.absorb_cli(raw, user_defaults, fallback).unwrap(); - - let conf = Configuration { - args: conf, - }; - - let conf = conf.into_command().unwrap().cmd; - - let mut expected = RunCmd { - allow_missing_blocks: false, - cache_config: Default::default(), - dirs: Default::default(), - spec: Default::default(), - pruning: Default::default(), - pruning_history: 128, - pruning_memory: 64, - daemon: None, - logger_config: Default::default(), - miner_options: Default::default(), - gas_price_percentile: 50, - poll_lifetime: 60, - ws_conf: Default::default(), - http_conf: Default::default(), - ipc_conf: Default::default(), - net_conf: default_network_config(), - network_id: None, - warp_sync: true, - warp_barrier: None, - acc_conf: Default::default(), - gas_pricer_conf: Default::default(), - miner_extras: Default::default(), - update_policy: UpdatePolicy { - enable_downloading: true, - require_consensus: true, - filter: UpdateFilter::Critical, - track: ReleaseTrack::Unknown, - path: default_hypervisor_path(), - max_size: 128 * 1024 * 1024, - max_delay: 100, - frequency: 20, - }, - mode: Default::default(), - tracing: Default::default(), - compaction: Default::default(), - geth_compatibility: false, - experimental_rpcs: false, - net_settings: Default::default(), - secretstore_conf: Default::default(), - private_provider_conf: Default::default(), - private_encryptor_conf: Default::default(), - private_tx_enabled: false, - name: "".into(), - custom_bootnodes: false, - fat_db: Default::default(), - snapshot_conf: Default::default(), - stratum: None, - check_seal: true, - download_old_blocks: true, - verifier_settings: Default::default(), - serve_light: true, - light: false, - no_hardcoded_sync: false, - no_persistent_txqueue: false, - max_round_blocks_to_import: 12, - on_demand_response_time_window: None, - on_demand_request_backoff_start: None, - on_demand_request_backoff_max: None, - on_demand_request_backoff_rounds_max: None, - on_demand_request_consecutive_failures: None, - }; - expected.secretstore_conf.enabled = cfg!(feature = "secretstore"); - expected.secretstore_conf.http_enabled = cfg!(feature = "secretstore"); - - assert_eq!(conf, Cmd::Run(expected)); - } - - #[test] - fn should_parse_mining_options() { - // given - let mut mining_options = MinerOptions::default(); - - // setting up 2 separate configs - let (mut conf0, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); - conf0.absorb_cli(raw, user_defaults, fallback).unwrap(); // default config - - let mut conf2 = conf0.clone(); - conf2.arg_tx_queue_strategy = "gas_price".to_owned(); // modified config - - let conf0 = Configuration { - args: conf0, - }; - - let conf2 = Configuration { - args: conf2, - }; - - // then - assert_eq!(conf0.miner_options().unwrap(), mining_options); - mining_options.tx_queue_strategy = PrioritizationStrategy::GasPriceOnly; - assert_eq!(conf2.miner_options().unwrap(), mining_options); - } - - #[test] - fn should_fail_on_force_reseal_and_reseal_min_period() { - let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); - conf.absorb_cli(raw, user_defaults, fallback).unwrap(); - - conf.arg_chain = "dev".to_owned(); - conf.flag_force_sealing = true; - conf.arg_reseal_min_period = 0; - - let conf = Configuration { - args: conf, - }; - - assert!(conf.miner_options().is_err()); - } - - #[test] - fn should_parse_updater_options() { - let (mut conf0, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); - conf0.absorb_cli(raw, user_defaults, fallback).unwrap(); - - conf0.arg_auto_update = "all".to_owned(); - conf0.arg_auto_update_delay = 300; - conf0.flag_no_consensus = true; - - let conf0 = Configuration { - args: conf0, - }; - - assert_eq!(conf0.update_policy().unwrap(), UpdatePolicy { - enable_downloading: true, - require_consensus: false, - filter: UpdateFilter::All, - track: ReleaseTrack::Unknown, - path: default_hypervisor_path(), - max_size: 128 * 1024 * 1024, - max_delay: 300, - frequency: 20, - }); - } - - #[test] - fn should_parse_network_settings() { - let (mut conf0, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); - conf0.absorb_cli(raw, user_defaults, fallback).unwrap(); - - conf0.arg_identity = "testname".to_owned(); - conf0.arg_chain = "goerli".to_owned(); - - let conf0 = Configuration { - args: conf0, - }; - - // then - assert_eq!(conf0.network_settings(), Ok(NetworkSettings { - name: "testname".to_owned(), - chain: "goerli".to_owned(), - is_dev_chain: false, - network_port: 30303, - rpc_enabled: true, - rpc_interface: "127.0.0.1".to_owned(), - rpc_port: 8545, - })); - } - - #[test] - fn should_parse_rpc_settings_with_geth_compatiblity() { - // given - fn assert(conf: Configuration) { - let net = conf.network_settings().unwrap(); - assert_eq!(net.rpc_enabled, true); - assert_eq!(net.rpc_interface, "0.0.0.0".to_owned()); - assert_eq!(net.rpc_port, 8000); - assert_eq!(conf.rpc_cors(), None); - assert_eq!(conf.rpc_apis(), "web3,eth".to_owned()); - } - - let (mut conf0, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); - conf0.absorb_cli(raw, user_defaults, fallback).unwrap(); - - let conf2 = conf0.clone(); - - conf0.arg_jsonrpc_port = 8000; - conf0.arg_jsonrpc_interface = "all".to_owned(); - conf0.arg_jsonrpc_cors = "*".to_owned(); - conf0.arg_jsonrpc_apis = "web3,eth".to_owned(); - - let conf0 = Configuration { - args: conf0, - }; - assert(conf0); - } - - #[test] - fn should_parse_rpc_hosts() { - // given - let (mut conf0, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); - conf0.absorb_cli(raw, user_defaults, fallback).unwrap(); - - let mut conf1 = conf0.clone(); - let mut conf2 = conf0.clone(); - let mut conf3 = conf0.clone(); - - conf1.arg_jsonrpc_hosts = "none".to_owned(); - conf2.arg_jsonrpc_hosts = "all".to_owned(); - conf3.arg_jsonrpc_hosts = "parity.io,something.io".to_owned(); - - let conf0 = Configuration { - args: conf0, - }; - - let conf1 = Configuration { - args: conf1, - }; - let conf2 = Configuration { - args: conf2, - }; - let conf3 = Configuration { - args: conf3, - }; - // then - assert_eq!(conf0.rpc_hosts(), Some(Vec::new())); - assert_eq!(conf1.rpc_hosts(), Some(Vec::new())); - assert_eq!(conf2.rpc_hosts(), None); - assert_eq!(conf3.rpc_hosts(), Some(vec!["parity.io".into(), "something.io".into()])); - } - - #[test] - fn should_respect_only_min_peers_and_default() { - let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); - conf.absorb_cli(raw, user_defaults, fallback).unwrap(); - - conf.arg_min_peers = Some(5); - - let conf = Configuration{ - args: conf, - }; - - match conf.into_command().unwrap().cmd { - Cmd::Run(c) => { - assert_eq!(c.net_conf.min_peers, 5); - assert_eq!(c.net_conf.max_peers, 50); - }, - _ => panic!("Should be Cmd::Run"), - } - } - - #[test] - fn should_respect_only_min_peers_and_greater_than_default() { - let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); - conf.absorb_cli(raw, user_defaults, fallback).unwrap(); - - conf.arg_min_peers = Some(500); - - let conf = Configuration{ - args: conf, - }; - - match conf.into_command().unwrap().cmd { - Cmd::Run(c) => { - assert_eq!(c.net_conf.min_peers, 500); - assert_eq!(c.net_conf.max_peers, 500); - }, - _ => panic!("Should be Cmd::Run"), - } - } - - #[test] - fn should_parse_secretstore_cors() { - let (mut conf0, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); - conf0.absorb_cli(raw, user_defaults, fallback).unwrap(); - - let mut conf1 = conf0.clone(); - let mut conf2 = conf0.clone(); - - conf1.arg_secretstore_http_cors = "*".to_owned(); - conf2.arg_secretstore_http_cors = "http://parity.io,http://something.io".to_owned(); - - let conf0 = Configuration{ - args: conf0, - }; - - let conf1 = Configuration{ - args: conf1, - }; - - let conf2 = Configuration{ - args: conf2, - }; - - // then - assert_eq!(conf0.secretstore_cors(), Some(vec![])); - assert_eq!(conf1.secretstore_cors(), None); - assert_eq!(conf2.secretstore_cors(), Some(vec!["http://parity.io".into(),"http://something.io".into()])); - } - - #[test] - fn ensures_sane_http_settings() { - let (mut conf0, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); - conf0.absorb_cli(raw, user_defaults, fallback).unwrap(); - - conf0.arg_jsonrpc_server_threads = Some(0); - conf0.arg_jsonrpc_max_payload = Some(0); - - let conf0 = Configuration { - args: conf0, - }; - - // then things are adjusted to Just Work. - let http_conf = conf0.http_config().unwrap(); - assert_eq!(http_conf.server_threads, 1); - assert_eq!(http_conf.max_payload, 1); - } - - #[test] - fn jsonrpc_threading_defaults() { - - let (mut conf, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); - conf.absorb_cli(raw, user_defaults, fallback).unwrap(); - - assert_eq!(conf.arg_jsonrpc_server_threads, Some(4)); - } - - #[test] - fn test_dev_preset() { - - let raw: ArgsInput = Default::default(); - let mut conf: Args = Default::default(); - - let (user_defaults, fallback) = Args::generate_default_configuration( - "config_dev.toml", - "config_default.toml" - ).unwrap(); - - conf.absorb_cli(raw, user_defaults, fallback).unwrap(); - - let conf = Configuration { - args: conf, - }; - - match conf.into_command().unwrap().cmd { - Cmd::Run(c) => { - assert_eq!(c.net_settings.chain, "dev"); - assert_eq!(c.gas_pricer_conf, GasPricerConfig::Fixed(0.into())); - assert_eq!(c.miner_options.reseal_min_period, Duration::from_millis(0)); - }, - _ => panic!("Should be Cmd::Run"), - } - } - - #[test] - fn test_mining_preset() { - - let raw: ArgsInput = Default::default(); - let mut conf: Args = Default::default(); - - let (user_defaults, fallback) = Args::generate_default_configuration( - "config_mining.toml", - "config_default.toml" - ).unwrap(); - - conf.absorb_cli(raw, user_defaults, fallback).unwrap(); - - let conf = Configuration { - args: conf, - }; - - match conf.into_command().unwrap().cmd { - Cmd::Run(c) => { - assert_eq!(c.net_conf.min_peers, 50); - assert_eq!(c.net_conf.max_peers, 100); - assert_eq!(c.ipc_conf.enabled, false); - assert_eq!(c.miner_options.force_sealing, true); - assert_eq!(c.miner_options.reseal_on_external_tx, true); - assert_eq!(c.miner_options.reseal_on_own_tx, true); - assert_eq!(c.miner_options.reseal_min_period, Duration::from_millis(4000)); - assert_eq!(c.miner_options.pool_limits.max_count, 8192); - assert_eq!(c.cache_config, CacheConfig::new_with_total_cache_size(1024)); - assert_eq!(c.logger_config.mode.unwrap(), "miner=trace,own_tx=trace"); - }, - _ => panic!("Should be Cmd::Run"), - } - } - - #[test] - fn test_non_standard_ports_preset() { - let raw: ArgsInput = Default::default(); - let mut conf: Args = Default::default(); - - let (user_defaults, fallback) = Args::generate_default_configuration( - "config_non_standard_ports.toml", - "config_default.toml" - ).unwrap(); - - conf.absorb_cli(raw, user_defaults, fallback).unwrap(); - - let conf = Configuration { - args: conf, - }; - - match conf.into_command().unwrap().cmd { - Cmd::Run(c) => { - assert_eq!(c.net_settings.network_port, 30305); - assert_eq!(c.net_settings.rpc_port, 8645); - }, - _ => panic!("Should be Cmd::Run"), - } - } - - #[test] - fn test_insecure_preset() { - - let raw: ArgsInput = Default::default(); - let mut conf: Args = Default::default(); - - let (user_defaults, fallback) = Args::generate_default_configuration( - "config_insecure.toml", - "config_default.toml" - ).unwrap(); - - conf.absorb_cli(raw, user_defaults, fallback).unwrap(); - - let conf = Configuration { - args: conf, - }; - - match conf.into_command().unwrap().cmd { - Cmd::Run(c) => { - assert_eq!(c.update_policy.require_consensus, false); - assert_eq!(c.net_settings.rpc_interface, "0.0.0.0"); - match c.http_conf.apis { - ApiSet::List(set) => assert_eq!(set, ApiSet::All.list_apis()), - _ => panic!("Incorrect rpc apis"), - } -; - assert_eq!(c.http_conf.hosts, None); - }, - _ => panic!("Should be Cmd::Run"), - } - } - - #[test] - fn test_dev_insecure_preset() { - - let raw: ArgsInput = Default::default(); - let mut conf: Args = Default::default(); - - let (user_defaults, fallback) = Args::generate_default_configuration( - "config_dev_insecure.toml", - "config_default.toml" - ).unwrap(); - - conf.absorb_cli(raw, user_defaults, fallback).unwrap(); - - let conf = Configuration { - args: conf, - }; - - match conf.into_command().unwrap().cmd { - Cmd::Run(c) => { - assert_eq!(c.net_settings.chain, "dev"); - assert_eq!(c.gas_pricer_conf, GasPricerConfig::Fixed(0.into())); - assert_eq!(c.miner_options.reseal_min_period, Duration::from_millis(0)); - assert_eq!(c.update_policy.require_consensus, false); - assert_eq!(c.net_settings.rpc_interface, "0.0.0.0"); - match c.http_conf.apis { - ApiSet::List(set) => assert_eq!(set, ApiSet::All.list_apis()), - _ => panic!("Incorrect rpc apis"), - } - // "web3,eth,net,personal,parity,parity_set,traces,rpc,parity_accounts"); - assert_eq!(c.http_conf.hosts, None); - }, - _ => panic!("Should be Cmd::Run"), - } - } - - #[test] - fn test_override_preset() { - - let mut raw: ArgsInput = Default::default(); - let mut conf: Args = Default::default(); - - raw.globals.networking.min_peers = Some(99); - - let (user_defaults, fallback) = Args::generate_default_configuration( - "config_mining.toml", - "config_default.toml" - ).unwrap(); - - conf.absorb_cli(raw, user_defaults, fallback).unwrap(); - - let conf = Configuration { - args: conf, - }; - - match conf.into_command().unwrap().cmd { - Cmd::Run(c) => { - assert_eq!(c.net_conf.min_peers, 99); - }, - _ => panic!("Should be Cmd::Run"), - } - } - - #[test] - fn test_identity_arg() { - let (mut conf0, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); - conf0.absorb_cli(raw, user_defaults, fallback).unwrap(); - - conf0.arg_identity = "Somebody".to_owned(); - - let conf0 = Configuration { - args: conf0 - }; - - match conf0.into_command().unwrap().cmd { - Cmd::Run(c) => { - assert_eq!(c.name, "Somebody"); - assert!(c.net_conf.client_version.starts_with("OpenEthereum/Somebody/")); - } - _ => panic!("Should be Cmd::Run"), - } - } - - #[test] - fn should_apply_ports_shift() { - // give - let (mut conf0, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); - conf0.absorb_cli(raw, user_defaults, fallback).unwrap(); - - let mut conf1 = conf0.clone(); - - conf0.arg_ports_shift = 1; - conf0.flag_stratum = true; - - conf1.arg_ports_shift = 1; - conf1.arg_jsonrpc_port = 8544; - - let conf0 = Configuration { - args: conf0 - }; - - let conf1 = Configuration { - args: conf1 - }; - - assert_eq!(conf0.net_addresses().unwrap().0.port(), 30304); - assert_eq!(conf0.network_settings().unwrap().network_port, 30304); - assert_eq!(conf0.network_settings().unwrap().rpc_port, 8546); - assert_eq!(conf0.http_config().unwrap().port, 8546); - assert_eq!(conf0.ws_config().unwrap().port, 8547); - assert_eq!(conf0.secretstore_config().unwrap().port, 8084); - assert_eq!(conf0.secretstore_config().unwrap().http_port, 8083); - assert_eq!(conf0.stratum_options().unwrap().unwrap().port, 8009); - - assert_eq!(conf1.net_addresses().unwrap().0.port(), 30304); - assert_eq!(conf1.network_settings().unwrap().network_port, 30304); - assert_eq!(conf1.network_settings().unwrap().rpc_port, 8545); - assert_eq!(conf1.http_config().unwrap().port, 8545); - assert_eq!(conf1.ws_config().unwrap().port, 8547); - assert_eq!(conf1.secretstore_config().unwrap().port, 8084); - assert_eq!(conf1.secretstore_config().unwrap().http_port, 8083); - } - - #[test] - fn should_resolve_external_nat_hosts() { - - let (mut conf0, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); - conf0.absorb_cli(raw, user_defaults, fallback).unwrap(); - - let mut conf1 = conf0.clone(); - let mut conf2 = conf0.clone(); - let mut conf3 = conf0.clone(); - let mut conf4 = conf0.clone(); - - conf0.arg_nat = "extip:1.1.1.1".to_owned(); - - let conf0 = Configuration { - args: conf0 - }; - - conf1.arg_nat = "extip:192.168.1.1:123".to_owned(); - let conf1 = Configuration { - args: conf1 - }; - - conf2.arg_nat = "extip:ethereum.org".to_owned(); - let conf2 = Configuration { - args: conf2 - }; - - conf3.arg_nat = "extip:ethereum.org:whatever bla bla 123".to_owned(); - let conf3 = Configuration { - args: conf3 - }; - - conf4.arg_nat = "extip:blabla".to_owned(); - let conf4 = Configuration { - args: conf4 - }; - // Ip works - assert_eq!(conf0.net_addresses().unwrap().1.unwrap().ip().to_string(), "1.1.1.1"); - assert_eq!(conf0.net_addresses().unwrap().1.unwrap().port(), 30303); - - // Ip with port works, port is discarded - assert_eq!(conf1.net_addresses().unwrap().1.unwrap().ip().to_string(), "192.168.1.1"); - assert_eq!(conf1.net_addresses().unwrap().1.unwrap().port(), 30303); - - // Hostname works - assert!(conf2.net_addresses().unwrap().1.is_some()); - assert_eq!(conf2.net_addresses().unwrap().1.unwrap().port(), 30303); - - // Hostname works, garbage at the end is discarded - assert!(conf3.net_addresses().unwrap().1.is_some()); - assert_eq!(conf3.net_addresses().unwrap().1.unwrap().port(), 30303); - - // Garbage is error - assert!(conf4.net_addresses().is_err()); - } - - #[test] - fn should_expose_all_servers() { - let (mut conf0, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); - conf0.absorb_cli(raw, user_defaults, fallback).unwrap(); - - conf0.flag_unsafe_expose = true; - - let conf0 = Configuration { - args: conf0 - }; - - assert_eq!(&conf0.network_settings().unwrap().rpc_interface, "0.0.0.0"); - assert_eq!(&conf0.http_config().unwrap().interface, "0.0.0.0"); - assert_eq!(conf0.http_config().unwrap().hosts, None); - assert_eq!(&conf0.ws_config().unwrap().interface, "0.0.0.0"); - assert_eq!(conf0.ws_config().unwrap().hosts, None); - assert_eq!(conf0.ws_config().unwrap().origins, None); - assert_eq!(&conf0.secretstore_config().unwrap().interface, "0.0.0.0"); - assert_eq!(&conf0.secretstore_config().unwrap().http_interface, "0.0.0.0"); - } - - #[test] - fn allow_ips() { - - let (mut all, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); - all.absorb_cli(raw, user_defaults, fallback).unwrap(); - - let mut private = all.clone(); - let mut block_custom = all.clone(); - let mut combo = all.clone(); - let mut ipv6_custom_public = all.clone(); - let mut ipv6_custom_private = all.clone(); - - all.arg_allow_ips = "all".to_owned(); - let all = Configuration { - args: all - }; - - private.arg_allow_ips = "private".to_owned(); - let private = Configuration { - args: private - }; - - block_custom.arg_allow_ips = "-10.0.0.0/8".to_owned(); - let block_custom = Configuration { - args: block_custom - }; - - combo.arg_allow_ips = "public 10.0.0.0/8 -1.0.0.0/8".to_owned(); - let combo = Configuration { - args: combo - }; - - ipv6_custom_public.arg_allow_ips = "public fc00::/7".to_owned(); - let ipv6_custom_public = Configuration { - args: ipv6_custom_public - }; - - ipv6_custom_private.arg_allow_ips = "private -fc00::/7".to_owned(); - let ipv6_custom_private = Configuration { - args: ipv6_custom_private - }; - - assert_eq!(all.ip_filter().unwrap(), IpFilter { - predefined: AllowIP::All, - custom_allow: vec![], - custom_block: vec![], - }); - - assert_eq!(private.ip_filter().unwrap(), IpFilter { - predefined: AllowIP::Private, - custom_allow: vec![], - custom_block: vec![], - }); - - assert_eq!(block_custom.ip_filter().unwrap(), IpFilter { - predefined: AllowIP::All, - custom_allow: vec![], - custom_block: vec![IpNetwork::from_str("10.0.0.0/8").unwrap()], - }); - - assert_eq!(combo.ip_filter().unwrap(), IpFilter { - predefined: AllowIP::Public, - custom_allow: vec![IpNetwork::from_str("10.0.0.0/8").unwrap()], - custom_block: vec![IpNetwork::from_str("1.0.0.0/8").unwrap()], - }); - - assert_eq!(ipv6_custom_public.ip_filter().unwrap(), IpFilter { - predefined: AllowIP::Public, - custom_allow: vec![IpNetwork::from_str("fc00::/7").unwrap()], - custom_block: vec![], - }); - - assert_eq!(ipv6_custom_private.ip_filter().unwrap(), IpFilter { - predefined: AllowIP::Private, - custom_allow: vec![], - custom_block: vec![IpNetwork::from_str("fc00::/7").unwrap()], - }); - } - - #[test] - fn should_use_correct_cache_path_if_base_is_set() { - use std::path; - - let (mut std, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); - std.absorb_cli(raw, user_defaults, fallback).unwrap(); - - let mut base = std.clone(); - base.arg_base_path = Some("/test".to_owned()); - - let std = Configuration { - args: std - }; - - let base = Configuration { - args: base - }; - - let base_path = ::dir::default_data_path(); - let local_path = ::dir::default_local_path(); - assert_eq!(std.directories().cache, dir::helpers::replace_home_and_local(&base_path, &local_path, ::dir::CACHE_PATH)); - assert_eq!(path::Path::new(&base.directories().cache), path::Path::new("/test/cache")); - } - - #[test] - fn should_respect_only_max_peers_and_default() { - - let (mut conf0, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); - conf0.absorb_cli(raw, user_defaults, fallback).unwrap(); - - conf0.arg_max_peers = Some(50); - - let conf0 = Configuration { - args: conf0 - }; - - match conf0.into_command().unwrap().cmd { - Cmd::Run(c) => { - assert_eq!(c.net_conf.min_peers, 25); - assert_eq!(c.net_conf.max_peers, 50); - }, - _ => panic!("Should be Cmd::Run"), - } - } - - #[test] - fn should_respect_only_max_peers_less_than_default() { - let (mut conf0, raw, user_defaults, fallback) = intialize_with_out_of_the_box_defaults(); - conf0.absorb_cli(raw, user_defaults, fallback).unwrap(); - - conf0.arg_max_peers = Some(5); - - let conf0 = Configuration { - args: conf0 - }; - - match conf0.into_command().unwrap().cmd { - Cmd::Run(c) => { - assert_eq!(c.net_conf.min_peers, 5); - assert_eq!(c.net_conf.max_peers, 5); - }, - _ => panic!("Should be Cmd::Run"), - } - } - -}