// Copyright 2015-2017 Parity Technologies (UK) Ltd. // This file is part of Parity. // Parity 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. // Parity 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 Parity. If not, see . #[macro_use] mod usage; use dir; usage! { { // Commands cmd_daemon: bool, cmd_wallet: bool, cmd_account: bool, cmd_new: bool, cmd_list: bool, cmd_export: bool, cmd_blocks: bool, cmd_state: bool, cmd_import: bool, cmd_signer: bool, cmd_new_token: bool, cmd_sign: bool, cmd_reject: bool, cmd_snapshot: bool, cmd_restore: bool, cmd_ui: bool, cmd_dapp: bool, cmd_tools: bool, cmd_hash: bool, cmd_kill: bool, cmd_db: bool, // Arguments arg_pid_file: String, arg_file: Option, arg_path: Vec, arg_id: Option, // Flags // -- Legacy Options flag_geth: bool, flag_testnet: bool, flag_import_geth_keys: bool, flag_datadir: Option, flag_networkid: Option, flag_peers: Option, flag_nodekey: Option, flag_nodiscover: bool, flag_jsonrpc: bool, flag_jsonrpc_off: bool, flag_webapp: bool, flag_dapps_off: bool, flag_rpc: bool, flag_rpcaddr: Option, flag_rpcport: Option, flag_rpcapi: Option, flag_rpccorsdomain: Option, flag_ipcdisable: bool, flag_ipc_off: bool, flag_ipcapi: Option, flag_ipcpath: Option, flag_gasprice: Option, flag_etherbase: Option, flag_extradata: Option, flag_cache: Option, // -- Miscellaneous Options flag_version: bool, flag_no_config: bool, } { // -- Operating Options flag_mode: String = "last", or |c: &Config| otry!(c.parity).mode.clone(), flag_mode_timeout: u64 = 300u64, or |c: &Config| otry!(c.parity).mode_timeout.clone(), flag_mode_alarm: u64 = 3600u64, or |c: &Config| otry!(c.parity).mode_alarm.clone(), flag_auto_update: String = "critical", or |c: &Config| otry!(c.parity).auto_update.clone(), flag_release_track: String = "current", or |c: &Config| otry!(c.parity).release_track.clone(), flag_public_node: bool = false, or |c: &Config| otry!(c.parity).public_node.clone(), flag_no_download: bool = false, or |c: &Config| otry!(c.parity).no_download.clone(), flag_no_consensus: bool = false, or |c: &Config| otry!(c.parity).no_consensus.clone(), flag_chain: String = "foundation", or |c: &Config| otry!(c.parity).chain.clone(), flag_keys_path: String = "$BASE/keys", or |c: &Config| otry!(c.parity).keys_path.clone(), flag_identity: String = "", or |c: &Config| otry!(c.parity).identity.clone(), flag_light: bool = false, or |c: &Config| otry!(c.parity).light, flag_no_persistent_txqueue: bool = false, or |c: &Config| otry!(c.parity).no_persistent_txqueue, // -- Convenience Options flag_config: String = "$BASE/config.toml", or |_| None, flag_ports_shift: u16 = 0u16, or |c: &Config| otry!(c.misc).ports_shift, flag_unsafe_expose: bool = false, or |c: &Config| otry!(c.misc).unsafe_expose, // -- Account Options flag_unlock: Option = None, or |c: &Config| otry!(c.account).unlock.as_ref().map(|vec| Some(vec.join(","))), flag_password: Vec = Vec::new(), or |c: &Config| otry!(c.account).password.clone(), flag_keys_iterations: u32 = 10240u32, or |c: &Config| otry!(c.account).keys_iterations.clone(), flag_no_hardware_wallets: bool = false, or |c: &Config| otry!(c.account).disable_hardware.clone(), flag_fast_unlock: bool = false, or |c: &Config| otry!(c.account).fast_unlock.clone(), flag_force_ui: bool = false, or |c: &Config| otry!(c.ui).force.clone(), flag_no_ui: bool = false, or |c: &Config| otry!(c.ui).disable.clone(), flag_ui_port: u16 = 8180u16, or |c: &Config| otry!(c.ui).port.clone(), flag_ui_interface: String = "local", or |c: &Config| otry!(c.ui).interface.clone(), flag_ui_hosts: String = "none", or |c: &Config| otry!(c.ui).hosts.as_ref().map(|vec| vec.join(",")), flag_ui_path: String = "$BASE/signer", or |c: &Config| otry!(c.ui).path.clone(), // NOTE [todr] For security reasons don't put this to config files flag_ui_no_validation: bool = false, or |_| None, // -- Networking Options flag_no_warp: bool = false, or |c: &Config| otry!(c.network).warp.clone().map(|w| !w), flag_port: u16 = 30303u16, or |c: &Config| otry!(c.network).port.clone(), flag_min_peers: u16 = 25u16, or |c: &Config| otry!(c.network).min_peers.clone(), flag_max_peers: u16 = 50u16, or |c: &Config| otry!(c.network).max_peers.clone(), flag_max_pending_peers: u16 = 64u16, or |c: &Config| otry!(c.network).max_pending_peers.clone(), flag_snapshot_peers: u16 = 0u16, or |c: &Config| otry!(c.network).snapshot_peers.clone(), flag_nat: String = "any", or |c: &Config| otry!(c.network).nat.clone(), flag_allow_ips: String = "all", or |c: &Config| otry!(c.network).allow_ips.clone(), flag_network_id: Option = None, or |c: &Config| otry!(c.network).id.clone().map(Some), flag_bootnodes: Option = None, or |c: &Config| otry!(c.network).bootnodes.as_ref().map(|vec| Some(vec.join(","))), flag_no_discovery: bool = false, or |c: &Config| otry!(c.network).discovery.map(|d| !d).clone(), flag_node_key: Option = None, or |c: &Config| otry!(c.network).node_key.clone().map(Some), flag_reserved_peers: Option = None, or |c: &Config| otry!(c.network).reserved_peers.clone().map(Some), flag_reserved_only: bool = false, or |c: &Config| otry!(c.network).reserved_only.clone(), flag_no_ancient_blocks: bool = false, or |_| None, flag_no_serve_light: bool = false, or |c: &Config| otry!(c.network).no_serve_light.clone(), // -- API and Console Options // RPC flag_no_jsonrpc: bool = false, or |c: &Config| otry!(c.rpc).disable.clone(), flag_jsonrpc_port: u16 = 8545u16, or |c: &Config| otry!(c.rpc).port.clone(), flag_jsonrpc_interface: String = "local", or |c: &Config| otry!(c.rpc).interface.clone(), flag_jsonrpc_cors: Option = None, or |c: &Config| otry!(c.rpc).cors.clone().map(Some), flag_jsonrpc_apis: String = "web3,eth,pubsub,net,parity,parity_pubsub,traces,rpc,secretstore", or |c: &Config| otry!(c.rpc).apis.as_ref().map(|vec| vec.join(",")), flag_jsonrpc_hosts: String = "none", or |c: &Config| otry!(c.rpc).hosts.as_ref().map(|vec| vec.join(",")), flag_jsonrpc_threads: Option = None, or |c: &Config| otry!(c.rpc).threads.map(Some), // WS flag_no_ws: bool = false, or |c: &Config| otry!(c.websockets).disable.clone(), flag_ws_port: u16 = 8546u16, or |c: &Config| otry!(c.websockets).port.clone(), flag_ws_interface: String = "local", or |c: &Config| otry!(c.websockets).interface.clone(), flag_ws_apis: String = "web3,eth,pubsub,net,parity,parity_pubsub,traces,rpc,secretstore", or |c: &Config| otry!(c.websockets).apis.as_ref().map(|vec| vec.join(",")), flag_ws_origins: String = "chrome-extension://*", or |c: &Config| otry!(c.websockets).origins.as_ref().map(|vec| vec.join(",")), flag_ws_hosts: String = "none", or |c: &Config| otry!(c.websockets).hosts.as_ref().map(|vec| vec.join(",")), // IPC flag_no_ipc: bool = false, or |c: &Config| otry!(c.ipc).disable.clone(), flag_ipc_path: String = if cfg!(windows) { r"\\.\pipe\jsonrpc.ipc" } else { "$BASE/jsonrpc.ipc" }, or |c: &Config| otry!(c.ipc).path.clone(), flag_ipc_apis: String = "web3,eth,pubsub,net,parity,parity_pubsub,parity_accounts,traces,rpc,secretstore", or |c: &Config| otry!(c.ipc).apis.as_ref().map(|vec| vec.join(",")), // DAPPS flag_no_dapps: bool = false, or |c: &Config| otry!(c.dapps).disable.clone(), flag_dapps_path: String = "$BASE/dapps", or |c: &Config| otry!(c.dapps).path.clone(), // Secret Store flag_no_secretstore: bool = false, or |c: &Config| otry!(c.secretstore).disable.clone(), flag_secretstore_secret: Option = None, or |c: &Config| otry!(c.secretstore).self_secret.clone().map(Some), flag_secretstore_nodes: String = "", or |c: &Config| otry!(c.secretstore).nodes.as_ref().map(|vec| vec.join(",")), flag_secretstore_interface: String = "local", or |c: &Config| otry!(c.secretstore).interface.clone(), flag_secretstore_port: u16 = 8083u16, or |c: &Config| otry!(c.secretstore).port.clone(), flag_secretstore_http_interface: String = "local", or |c: &Config| otry!(c.secretstore).http_interface.clone(), flag_secretstore_http_port: u16 = 8082u16, or |c: &Config| otry!(c.secretstore).http_port.clone(), flag_secretstore_path: String = "$BASE/secretstore", or |c: &Config| otry!(c.secretstore).path.clone(), // IPFS flag_ipfs_api: bool = false, or |c: &Config| otry!(c.ipfs).enable.clone(), flag_ipfs_api_port: u16 = 5001u16, or |c: &Config| otry!(c.ipfs).port.clone(), flag_ipfs_api_interface: String = "local", or |c: &Config| otry!(c.ipfs).interface.clone(), flag_ipfs_api_cors: Option = None, or |c: &Config| otry!(c.ipfs).cors.clone().map(Some), flag_ipfs_api_hosts: String = "none", or |c: &Config| otry!(c.ipfs).hosts.as_ref().map(|vec| vec.join(",")), // -- Sealing/Mining Options flag_author: Option = None, or |c: &Config| otry!(c.mining).author.clone().map(Some), flag_engine_signer: Option = None, or |c: &Config| otry!(c.mining).engine_signer.clone().map(Some), flag_force_sealing: bool = false, or |c: &Config| otry!(c.mining).force_sealing.clone(), flag_reseal_on_txs: String = "own", or |c: &Config| otry!(c.mining).reseal_on_txs.clone(), flag_reseal_on_uncle: bool = false, or |c: &Config| otry!(c.mining).reseal_on_uncle.clone(), flag_reseal_min_period: u64 = 2000u64, or |c: &Config| otry!(c.mining).reseal_min_period.clone(), flag_reseal_max_period: u64 = 120000u64, or |c: &Config| otry!(c.mining).reseal_max_period.clone(), flag_work_queue_size: usize = 20usize, or |c: &Config| otry!(c.mining).work_queue_size.clone(), flag_tx_gas_limit: Option = None, or |c: &Config| otry!(c.mining).tx_gas_limit.clone().map(Some), flag_tx_time_limit: Option = None, or |c: &Config| otry!(c.mining).tx_time_limit.clone().map(Some), flag_relay_set: String = "cheap", or |c: &Config| otry!(c.mining).relay_set.clone(), flag_usd_per_tx: String = "0.0025", or |c: &Config| otry!(c.mining).usd_per_tx.clone(), flag_usd_per_eth: String = "auto", or |c: &Config| otry!(c.mining).usd_per_eth.clone(), flag_price_update_period: String = "hourly", or |c: &Config| otry!(c.mining).price_update_period.clone(), flag_gas_floor_target: String = "4700000", or |c: &Config| otry!(c.mining).gas_floor_target.clone(), flag_gas_cap: String = "6283184", or |c: &Config| otry!(c.mining).gas_cap.clone(), flag_extra_data: Option = None, or |c: &Config| otry!(c.mining).extra_data.clone().map(Some), flag_tx_queue_size: usize = 1024usize, or |c: &Config| otry!(c.mining).tx_queue_size.clone(), flag_tx_queue_gas: String = "auto", or |c: &Config| otry!(c.mining).tx_queue_gas.clone(), flag_tx_queue_strategy: String = "gas_price", or |c: &Config| otry!(c.mining).tx_queue_strategy.clone(), flag_tx_queue_ban_count: u16 = 1u16, or |c: &Config| otry!(c.mining).tx_queue_ban_count.clone(), flag_tx_queue_ban_time: u16 = 180u16, or |c: &Config| otry!(c.mining).tx_queue_ban_time.clone(), flag_remove_solved: bool = false, or |c: &Config| otry!(c.mining).remove_solved.clone(), flag_notify_work: Option = None, or |c: &Config| otry!(c.mining).notify_work.as_ref().map(|vec| Some(vec.join(","))), flag_refuse_service_transactions: bool = false, or |c: &Config| otry!(c.mining).refuse_service_transactions.clone(), flag_stratum: bool = false, or |c: &Config| Some(c.stratum.is_some()), flag_stratum_interface: String = "local", or |c: &Config| otry!(c.stratum).interface.clone(), flag_stratum_port: u16 = 8008u16, or |c: &Config| otry!(c.stratum).port.clone(), flag_stratum_secret: Option = None, or |c: &Config| otry!(c.stratum).secret.clone().map(Some), // -- Footprint Options flag_tracing: String = "auto", or |c: &Config| otry!(c.footprint).tracing.clone(), flag_pruning: String = "auto", or |c: &Config| otry!(c.footprint).pruning.clone(), flag_pruning_history: u64 = 64u64, or |c: &Config| otry!(c.footprint).pruning_history.clone(), flag_pruning_memory: usize = 32usize, or |c: &Config| otry!(c.footprint).pruning_memory.clone(), flag_cache_size_db: u32 = 32u32, or |c: &Config| otry!(c.footprint).cache_size_db.clone(), flag_cache_size_blocks: u32 = 8u32, or |c: &Config| otry!(c.footprint).cache_size_blocks.clone(), flag_cache_size_queue: u32 = 40u32, or |c: &Config| otry!(c.footprint).cache_size_queue.clone(), flag_cache_size_state: u32 = 25u32, or |c: &Config| otry!(c.footprint).cache_size_state.clone(), flag_cache_size: Option = None, or |c: &Config| otry!(c.footprint).cache_size.clone().map(Some), flag_fast_and_loose: bool = false, or |c: &Config| otry!(c.footprint).fast_and_loose.clone(), flag_db_compaction: String = "auto", or |c: &Config| otry!(c.footprint).db_compaction.clone(), flag_fat_db: String = "auto", or |c: &Config| otry!(c.footprint).fat_db.clone(), flag_scale_verifiers: bool = false, or |c: &Config| otry!(c.footprint).scale_verifiers.clone(), flag_num_verifiers: Option = None, or |c: &Config| otry!(c.footprint).num_verifiers.clone().map(Some), // -- Import/Export Options flag_from: String = "1", or |_| None, flag_to: String = "latest", or |_| None, flag_format: Option = None, or |_| None, flag_no_seal_check: bool = false, or |_| None, flag_no_storage: bool = false, or |_| None, flag_no_code: bool = false, or |_| None, flag_min_balance: Option = None, or |_| None, flag_max_balance: Option = None, or |_| None, // -- Snapshot Optons flag_at: String = "latest", or |_| None, flag_no_periodic_snapshot: bool = false, or |c: &Config| otry!(c.snapshots).disable_periodic.clone(), // -- Virtual Machine Options flag_jitvm: bool = false, or |c: &Config| otry!(c.vm).jit.clone(), // -- Miscellaneous Options flag_logging: Option = None, or |c: &Config| otry!(c.misc).logging.clone().map(Some), flag_log_file: Option = None, or |c: &Config| otry!(c.misc).log_file.clone().map(Some), flag_no_color: bool = false, or |c: &Config| otry!(c.misc).color.map(|c| !c).clone(), // -- Legacy Options supported in configs flag_dapps_port: Option = None, or |c: &Config| otry!(c.dapps).port.clone().map(Some), flag_dapps_interface: Option = None, or |c: &Config| otry!(c.dapps).interface.clone().map(Some), flag_dapps_hosts: Option = None, or |c: &Config| otry!(c.dapps).hosts.as_ref().map(|vec| Some(vec.join(","))), flag_dapps_cors: Option = None, or |c: &Config| otry!(c.dapps).cors.clone().map(Some), flag_dapps_user: Option = None, or |c: &Config| otry!(c.dapps).user.clone().map(Some), flag_dapps_pass: Option = None, or |c: &Config| otry!(c.dapps).pass.clone().map(Some), flag_dapps_apis_all: Option = None, or |_| None, } { // Values with optional default value. flag_base_path: Option, display dir::default_data_path(), or |c: &Config| otry!(c.parity).base_path.clone().map(Some), flag_db_path: Option, display dir::CHAINS_PATH, or |c: &Config| otry!(c.parity).db_path.clone().map(Some), flag_warp: Option, display true, or |c: &Config| Some(otry!(c.network).warp.clone()), } } #[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, ipfs: Option, mining: Option, footprint: Option, snapshots: Option, vm: Option, misc: Option, stratum: Option, } #[derive(Default, Debug, PartialEq, Deserialize)] struct Operating { mode: Option, mode_timeout: Option, mode_alarm: Option, auto_update: Option, release_track: Option, public_node: 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, } #[derive(Default, Debug, PartialEq, Deserialize)] struct Account { unlock: Option>, password: Option>, keys_iterations: Option, disable_hardware: Option, fast_unlock: Option, } #[derive(Default, Debug, PartialEq, Deserialize)] struct Ui { force: Option, disable: Option, port: Option, interface: Option, hosts: Option>, path: Option, } #[derive(Default, Debug, PartialEq, Deserialize)] struct Network { warp: Option, port: 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)] struct Rpc { disable: Option, port: Option, interface: Option, cors: Option, apis: Option>, hosts: Option>, threads: Option, } #[derive(Default, Debug, PartialEq, Deserialize)] struct Ws { disable: Option, port: Option, interface: Option, apis: Option>, origins: Option>, hosts: Option>, } #[derive(Default, Debug, PartialEq, Deserialize)] struct Ipc { disable: Option, path: Option, apis: Option>, } #[derive(Default, Debug, PartialEq, Deserialize)] struct Dapps { disable: Option, port: Option, interface: Option, hosts: Option>, cors: Option, path: Option, user: Option, pass: Option, } #[derive(Default, Debug, PartialEq, Deserialize)] struct SecretStore { disable: Option, self_secret: Option, nodes: Option>, interface: Option, port: Option, http_interface: Option, http_port: Option, path: Option, } #[derive(Default, Debug, PartialEq, Deserialize)] struct Ipfs { enable: Option, port: Option, interface: Option, cors: Option, hosts: Option>, } #[derive(Default, Debug, PartialEq, Deserialize)] 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, 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_gas: Option, tx_queue_strategy: Option, tx_queue_ban_count: Option, tx_queue_ban_time: Option, remove_solved: Option, notify_work: Option>, refuse_service_transactions: Option, } #[derive(Default, Debug, PartialEq, Deserialize)] struct Stratum { interface: Option, port: Option, secret: Option, } #[derive(Default, Debug, PartialEq, Deserialize)] 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)] struct Snapshots { disable_periodic: Option, } #[derive(Default, Debug, PartialEq, Deserialize)] struct VM { jit: Option, } #[derive(Default, Debug, PartialEq, Deserialize)] struct Misc { logging: Option, log_file: Option, color: Option, ports_shift: Option, unsafe_expose: Option, } #[cfg(test)] mod tests { use super::{ Args, ArgsError, Config, Operating, Account, Ui, Network, Ws, Rpc, Ipc, Dapps, Ipfs, Mining, Footprint, Snapshots, VM, Misc, SecretStore, }; use toml; #[test] fn should_parse_args_and_include_config() { // given let mut config = Config::default(); let mut operating = Operating::default(); operating.chain = Some("morden".into()); config.parity = Some(operating); // when let args = Args::parse_with_config(&["parity"], config).unwrap(); // then assert_eq!(args.flag_chain, "morden".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("morden".into()); config.parity = Some(operating); // when let args = Args::parse_with_config(&["parity", "--chain", "xyz"], config).unwrap(); // then assert_eq!(args.flag_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.flag_pruning_history, 128); } #[test] fn should_parse_full_config() { // given let config = toml::from_str(include_str!("./config.full.toml")).unwrap(); // when let args = Args::parse_with_config(&["parity", "--chain", "xyz"], config).unwrap(); // then assert_eq!(args, Args { // Commands cmd_daemon: false, cmd_wallet: false, cmd_account: false, cmd_new: false, cmd_list: false, cmd_export: false, cmd_state: false, cmd_blocks: false, cmd_import: false, cmd_signer: false, cmd_sign: false, cmd_reject: false, cmd_new_token: false, cmd_snapshot: false, cmd_restore: false, cmd_ui: false, cmd_dapp: false, cmd_tools: false, cmd_hash: false, cmd_db: false, cmd_kill: false, // Arguments arg_pid_file: "".into(), arg_file: None, arg_id: None, arg_path: vec![], // -- Operating Options flag_mode: "last".into(), flag_mode_timeout: 300u64, flag_mode_alarm: 3600u64, flag_auto_update: "none".into(), flag_release_track: "current".into(), flag_public_node: false, flag_no_download: false, flag_no_consensus: false, flag_chain: "xyz".into(), flag_base_path: Some("$HOME/.parity".into()), flag_db_path: Some("$HOME/.parity/chains".into()), flag_keys_path: "$HOME/.parity/keys".into(), flag_identity: "".into(), flag_light: false, flag_no_persistent_txqueue: false, // -- Convenience Options flag_config: "$BASE/config.toml".into(), flag_ports_shift: 0, flag_unsafe_expose: false, // -- Account Options flag_unlock: Some("0xdeadbeefcafe0000000000000000000000000000".into()), flag_password: vec!["~/.safe/password.file".into()], flag_keys_iterations: 10240u32, flag_no_hardware_wallets: false, flag_fast_unlock: false, flag_force_ui: false, flag_no_ui: false, flag_ui_port: 8180u16, flag_ui_interface: "127.0.0.1".into(), flag_ui_hosts: "none".into(), flag_ui_path: "$HOME/.parity/signer".into(), flag_ui_no_validation: false, // -- Networking Options flag_no_warp: false, flag_port: 30303u16, flag_min_peers: 25u16, flag_max_peers: 50u16, flag_max_pending_peers: 64u16, flag_snapshot_peers: 0u16, flag_allow_ips: "all".into(), flag_nat: "any".into(), flag_network_id: Some(1), flag_bootnodes: Some("".into()), flag_no_discovery: false, flag_node_key: None, flag_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_port: 8545u16, flag_jsonrpc_interface: "local".into(), flag_jsonrpc_cors: Some("null".into()), flag_jsonrpc_apis: "web3,eth,net,parity,traces,rpc,secretstore".into(), flag_jsonrpc_hosts: "none".into(), flag_jsonrpc_threads: None, // WS flag_no_ws: false, flag_ws_port: 8546u16, flag_ws_interface: "local".into(), flag_ws_apis: "web3,eth,net,parity,traces,rpc,secretstore".into(), flag_ws_origins: "none".into(), flag_ws_hosts: "none".into(), // IPC flag_no_ipc: false, flag_ipc_path: "$HOME/.parity/jsonrpc.ipc".into(), flag_ipc_apis: "web3,eth,net,parity,parity_accounts,personal,traces,rpc,secretstore".into(), // DAPPS flag_dapps_path: "$HOME/.parity/dapps".into(), flag_no_dapps: false, flag_no_secretstore: false, flag_secretstore_secret: None, flag_secretstore_nodes: "".into(), flag_secretstore_interface: "local".into(), flag_secretstore_port: 8083u16, flag_secretstore_http_interface: "local".into(), flag_secretstore_http_port: 8082u16, flag_secretstore_path: "$HOME/.parity/secretstore".into(), // IPFS flag_ipfs_api: false, flag_ipfs_api_port: 5001u16, flag_ipfs_api_interface: "local".into(), flag_ipfs_api_cors: Some("null".into()), flag_ipfs_api_hosts: "none".into(), // -- Sealing/Mining Options flag_author: Some("0xdeadbeefcafe0000000000000000000000000001".into()), flag_engine_signer: Some("0xdeadbeefcafe0000000000000000000000000001".into()), flag_force_sealing: true, flag_reseal_on_txs: "all".into(), flag_reseal_min_period: 4000u64, flag_reseal_max_period: 60000u64, flag_reseal_on_uncle: false, flag_work_queue_size: 20usize, flag_tx_gas_limit: Some("6283184".into()), flag_tx_time_limit: Some(100u64), flag_relay_set: "cheap".into(), flag_usd_per_tx: "0.0025".into(), flag_usd_per_eth: "auto".into(), flag_price_update_period: "hourly".into(), flag_gas_floor_target: "4700000".into(), flag_gas_cap: "6283184".into(), flag_extra_data: Some("Parity".into()), flag_tx_queue_size: 1024usize, flag_tx_queue_gas: "auto".into(), flag_tx_queue_strategy: "gas_factor".into(), flag_tx_queue_ban_count: 1u16, flag_tx_queue_ban_time: 180u16, flag_remove_solved: false, flag_notify_work: Some("http://localhost:3001".into()), flag_refuse_service_transactions: false, flag_stratum: false, flag_stratum_interface: "local".to_owned(), flag_stratum_port: 8008u16, flag_stratum_secret: None, // -- Footprint Options flag_tracing: "auto".into(), flag_pruning: "auto".into(), flag_pruning_history: 64u64, flag_pruning_memory: 500usize, flag_cache_size_db: 64u32, flag_cache_size_blocks: 8u32, flag_cache_size_queue: 50u32, flag_cache_size_state: 25u32, flag_cache_size: Some(128), flag_fast_and_loose: false, flag_db_compaction: "ssd".into(), flag_fat_db: "auto".into(), flag_scale_verifiers: true, flag_num_verifiers: Some(6), // -- Import/Export Options flag_from: "1".into(), flag_to: "latest".into(), flag_format: None, flag_no_seal_check: false, flag_no_code: false, flag_no_storage: false, flag_min_balance: None, flag_max_balance: None, // -- Snapshot Optons flag_at: "latest".into(), flag_no_periodic_snapshot: false, // -- Virtual Machine Options flag_jitvm: false, // -- Legacy Options flag_geth: false, flag_testnet: false, flag_import_geth_keys: false, flag_datadir: None, flag_networkid: None, flag_peers: None, flag_nodekey: None, flag_nodiscover: false, flag_jsonrpc: false, flag_jsonrpc_off: false, flag_webapp: false, flag_dapps_off: false, flag_rpc: false, flag_rpcaddr: None, flag_rpcport: None, flag_rpcapi: None, flag_rpccorsdomain: None, flag_ipcdisable: false, flag_ipc_off: false, flag_ipcapi: None, flag_ipcpath: None, flag_gasprice: None, flag_etherbase: None, flag_extradata: None, flag_cache: None, flag_warp: Some(true), // Legacy-Dapps flag_dapps_port: Some(8080), flag_dapps_interface: Some("local".into()), flag_dapps_hosts: Some("none".into()), flag_dapps_cors: None, flag_dapps_user: Some("test_user".into()), flag_dapps_pass: Some("test_pass".into()), flag_dapps_apis_all: None, // -- Miscellaneous Options flag_version: false, flag_logging: Some("own_tx=trace".into()), flag_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!("./config.invalid1.toml")); let config2 = Args::parse_config(include_str!("./config.invalid2.toml")); let config3 = Args::parse_config(include_str!("./config.invalid3.toml")); match (config1, config2, config3) { (Err(ArgsError::Decode(_)), Err(ArgsError::Decode(_)), Err(ArgsError::Decode(_))) => {}, (a, b, c) => { assert!(false, "Got invalid error types: {:?}, {:?}, {:?}", a, b, c); } } } #[test] fn should_deserialize_toml_file() { let config: Config = toml::from_str(include_str!("./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, release_track: None, public_node: 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_persistent_txqueue: None, }), account: Some(Account { unlock: Some(vec!["0x1".into(), "0x2".into(), "0x3".into()]), password: Some(vec!["passwdfile path".into()]), keys_iterations: None, disable_hardware: None, fast_unlock: None, }), ui: Some(Ui { force: None, disable: Some(true), port: None, interface: None, hosts: None, path: None, }), network: Some(Network { warp: Some(false), port: 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, }), rpc: Some(Rpc { disable: Some(true), port: Some(8180), interface: None, cors: None, apis: None, hosts: None, threads: None, }), ipc: Some(Ipc { disable: None, path: None, apis: Some(vec!["rpc".into(), "eth".into()]), }), dapps: Some(Dapps { disable: None, port: Some(8080), path: None, interface: None, hosts: None, cors: None, user: Some("username".into()), pass: Some("password".into()) }), secretstore: Some(SecretStore { disable: None, self_secret: None, nodes: None, interface: None, port: Some(8083), http_interface: None, http_port: Some(8082), path: None, }), ipfs: Some(Ipfs { enable: Some(false), port: Some(5001), interface: None, cors: None, hosts: 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, 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(1024), tx_queue_gas: Some("auto".into()), tx_queue_strategy: None, tx_queue_ban_count: None, tx_queue_ban_time: None, tx_gas_limit: None, tx_time_limit: None, extra_data: None, remove_solved: None, notify_work: None, refuse_service_transactions: 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(128), 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, }), snapshots: Some(Snapshots { disable_periodic: Some(true), }), vm: Some(VM { jit: Some(false), }), 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), }), stratum: None, }); } }