Merge remote-tracking branch 'parity/master' into bft

This commit is contained in:
keorn
2016-11-15 10:26:37 +00:00
400 changed files with 13886 additions and 3861 deletions

View File

@@ -21,7 +21,6 @@ use std::time::{Instant, Duration};
use std::thread::sleep;
use std::sync::Arc;
use rustc_serialize::hex::FromHex;
use ethcore_logger::{setup_log, Config as LogConfig};
use io::{PanicHandler, ForwardPanic};
use util::{ToPretty, Uint};
use rlp::PayloadInfo;
@@ -71,7 +70,6 @@ pub enum BlockchainCmd {
#[derive(Debug, PartialEq)]
pub struct ImportBlockchain {
pub spec: SpecType,
pub logger_config: LogConfig,
pub cache_config: CacheConfig,
pub dirs: Directories,
pub file_path: Option<String>,
@@ -80,17 +78,16 @@ pub struct ImportBlockchain {
pub pruning_history: u64,
pub compaction: DatabaseCompactionProfile,
pub wal: bool,
pub mode: Mode,
pub tracing: Switch,
pub fat_db: Switch,
pub vm_type: VMType,
pub check_seal: bool,
pub with_color: bool,
}
#[derive(Debug, PartialEq)]
pub struct ExportBlockchain {
pub spec: SpecType,
pub logger_config: LogConfig,
pub cache_config: CacheConfig,
pub dirs: Directories,
pub file_path: Option<String>,
@@ -99,7 +96,6 @@ pub struct ExportBlockchain {
pub pruning_history: u64,
pub compaction: DatabaseCompactionProfile,
pub wal: bool,
pub mode: Mode,
pub fat_db: Switch,
pub tracing: Switch,
pub from_block: BlockID,
@@ -120,9 +116,6 @@ fn execute_import(cmd: ImportBlockchain) -> Result<String, String> {
// Setup panic handler
let panic_handler = PanicHandler::new_in_arc();
// Setup logging
let _logger = setup_log(&cmd.logger_config);
// create dirs used by parity
try!(cmd.dirs.create_dirs());
@@ -160,7 +153,7 @@ fn execute_import(cmd: ImportBlockchain) -> Result<String, String> {
try!(execute_upgrades(&db_dirs, algorithm, cmd.compaction.compaction_profile(db_dirs.fork_path().as_path())));
// prepare client config
let client_config = to_client_config(&cmd.cache_config, cmd.mode, tracing, fat_db, cmd.compaction, cmd.wal, cmd.vm_type, "".into(), algorithm, cmd.pruning_history, cmd.check_seal);
let client_config = to_client_config(&cmd.cache_config, Mode::Active, tracing, fat_db, cmd.compaction, cmd.wal, cmd.vm_type, "".into(), algorithm, cmd.pruning_history, cmd.check_seal);
// build client
let service = try!(ClientService::start(
@@ -196,7 +189,7 @@ fn execute_import(cmd: ImportBlockchain) -> Result<String, String> {
}
};
let informant = Informant::new(client.clone(), None, None, None, cmd.logger_config.color);
let informant = Informant::new(client.clone(), None, None, None, cmd.with_color);
try!(service.register_io_handler(Arc::new(ImportIoHandler {
info: Arc::new(informant),
@@ -269,9 +262,6 @@ fn execute_export(cmd: ExportBlockchain) -> Result<String, String> {
// Setup panic handler
let panic_handler = PanicHandler::new_in_arc();
// Setup logging
let _logger = setup_log(&cmd.logger_config);
// create dirs used by parity
try!(cmd.dirs.create_dirs());
@@ -311,7 +301,7 @@ fn execute_export(cmd: ExportBlockchain) -> Result<String, String> {
try!(execute_upgrades(&db_dirs, algorithm, cmd.compaction.compaction_profile(db_dirs.fork_path().as_path())));
// prepare client config
let client_config = to_client_config(&cmd.cache_config, cmd.mode, tracing, fat_db, cmd.compaction, cmd.wal, VMType::default(), "".into(), algorithm, cmd.pruning_history, cmd.check_seal);
let client_config = to_client_config(&cmd.cache_config, Mode::Active, tracing, fat_db, cmd.compaction, cmd.wal, VMType::default(), "".into(), algorithm, cmd.pruning_history, cmd.check_seal);
let service = try!(ClientService::start(
client_config,

View File

@@ -1,5 +1,5 @@
[parity]
mode = "active"
mode = "last"
mode_timeout = 300
mode_alarm = 3600
chain = "homestead"
@@ -12,7 +12,7 @@ unlock = ["0xdeadbeefcafe0000000000000000000000000000"]
password = ["~/.safe/password.file"]
keys_iterations = 10240
[signer]
[ui]
force = false
disable = false
port = 8180
@@ -25,7 +25,7 @@ port = 30303
min_peers = 25
max_peers = 50
nat = "any"
id = "0x1"
id = 1
bootnodes = []
discovery = true
warp = true
@@ -41,13 +41,13 @@ disable = false
port = 8545
interface = "local"
cors = "null"
apis = ["web3", "eth", "net", "ethcore", "traces", "rpc", "personal_safe"]
apis = ["web3", "eth", "net", "parity", "traces", "rpc"]
hosts = ["none"]
[ipc]
disable = false
path = "$HOME/.parity/jsonrpc.ipc"
apis = ["web3", "eth", "net", "ethcore", "traces", "rpc", "personal_safe"]
apis = ["web3", "eth", "net", "parity", "parity_accounts", "personal", "traces", "rpc"]
[dapps]
disable = false

View File

@@ -8,7 +8,7 @@ chain = "./chain.json"
unlock = ["0x1", "0x2", "0x3"]
password = ["passwdfile path"]
[signer]
[ui]
disable = true
[network]

View File

@@ -46,7 +46,7 @@ usage! {
flag_testnet: bool,
flag_import_geth_keys: bool,
flag_datadir: Option<String>,
flag_networkid: Option<String>,
flag_networkid: Option<usize>,
flag_peers: Option<u16>,
flag_nodekey: Option<String>,
flag_nodiscover: bool,
@@ -74,7 +74,7 @@ usage! {
}
{
// -- Operating Options
flag_mode: String = "active", or |c: &Config| otry!(c.parity).mode.clone(),
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_chain: String = "homestead", or |c: &Config| otry!(c.parity).chain.clone(),
@@ -90,22 +90,20 @@ usage! {
flag_keys_iterations: u32 = 10240u32,
or |c: &Config| otry!(c.account).keys_iterations.clone(),
flag_force_signer: bool = false,
or |c: &Config| otry!(c.signer).force.clone(),
flag_no_signer: bool = false,
or |c: &Config| otry!(c.signer).disable.clone(),
flag_signer_port: u16 = 8180u16,
or |c: &Config| otry!(c.signer).port.clone(),
flag_signer_interface: String = "local",
or |c: &Config| otry!(c.signer).interface.clone(),
flag_signer_path: String = "$HOME/.parity/signer",
or |c: &Config| otry!(c.signer).path.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_path: String = "$HOME/.parity/signer",
or |c: &Config| otry!(c.ui).path.clone(),
// NOTE [todr] For security reasons don't put this to config files
flag_signer_no_validation: bool = false, or |_| None,
flag_ui_no_validation: bool = false, or |_| None,
// -- Networking Options
flag_no_network: bool = false,
or |c: &Config| otry!(c.network).disable.clone(),
flag_warp: bool = false,
or |c: &Config| otry!(c.network).warp.clone(),
flag_port: u16 = 30303u16,
@@ -122,7 +120,7 @@ usage! {
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<String> = None,
flag_network_id: Option<usize> = None,
or |c: &Config| otry!(c.network).id.clone().map(Some),
flag_bootnodes: Option<String> = None,
or |c: &Config| otry!(c.network).bootnodes.clone().map(|vec| Some(vec.join(","))),
@@ -145,7 +143,7 @@ usage! {
or |c: &Config| otry!(c.rpc).interface.clone(),
flag_jsonrpc_cors: Option<String> = None,
or |c: &Config| otry!(c.rpc).cors.clone().map(Some),
flag_jsonrpc_apis: String = "web3,eth,net,ethcore,traces,rpc,personal_safe",
flag_jsonrpc_apis: String = "web3,eth,net,parity,traces,rpc",
or |c: &Config| otry!(c.rpc).apis.clone().map(|vec| vec.join(",")),
flag_jsonrpc_hosts: String = "none",
or |c: &Config| otry!(c.rpc).hosts.clone().map(|vec| vec.join(",")),
@@ -155,7 +153,7 @@ usage! {
or |c: &Config| otry!(c.ipc).disable.clone(),
flag_ipc_path: String = "$HOME/.parity/jsonrpc.ipc",
or |c: &Config| otry!(c.ipc).path.clone(),
flag_ipc_apis: String = "web3,eth,net,ethcore,traces,rpc,personal_safe",
flag_ipc_apis: String = "web3,eth,net,parity,parity_accounts,traces,rpc",
or |c: &Config| otry!(c.ipc).apis.clone().map(|vec| vec.join(",")),
// DAPPS
@@ -273,7 +271,7 @@ usage! {
struct Config {
parity: Option<Operating>,
account: Option<Account>,
signer: Option<Signer>,
ui: Option<Ui>,
network: Option<Network>,
rpc: Option<Rpc>,
ipc: Option<Ipc>,
@@ -304,7 +302,7 @@ struct Account {
}
#[derive(Default, Debug, PartialEq, RustcDecodable)]
struct Signer {
struct Ui {
force: Option<bool>,
disable: Option<bool>,
port: Option<u16>,
@@ -323,7 +321,7 @@ struct Network {
max_pending_peers: Option<u16>,
nat: Option<String>,
allow_ips: Option<String>,
id: Option<String>,
id: Option<usize>,
bootnodes: Option<Vec<String>>,
discovery: Option<bool>,
node_key: Option<String>,
@@ -420,7 +418,7 @@ struct Misc {
mod tests {
use super::{
Args, ArgsError,
Config, Operating, Account, Signer, Network, Rpc, Ipc, Dapps, Mining, Footprint, Snapshots, VM, Misc
Config, Operating, Account, Ui, Network, Rpc, Ipc, Dapps, Mining, Footprint, Snapshots, VM, Misc
};
use toml;
@@ -500,7 +498,7 @@ mod tests {
arg_path: vec![],
// -- Operating Options
flag_mode: "active".into(),
flag_mode: "last".into(),
flag_mode_timeout: 300u64,
flag_mode_alarm: 3600u64,
flag_chain: "xyz".into(),
@@ -513,15 +511,14 @@ mod tests {
flag_password: vec!["~/.safe/password.file".into()],
flag_keys_iterations: 10240u32,
flag_force_signer: false,
flag_no_signer: false,
flag_signer_port: 8180u16,
flag_signer_interface: "127.0.0.1".into(),
flag_signer_path: "$HOME/.parity/signer".into(),
flag_signer_no_validation: false,
flag_force_ui: false,
flag_no_ui: false,
flag_ui_port: 8180u16,
flag_ui_interface: "127.0.0.1".into(),
flag_ui_path: "$HOME/.parity/signer".into(),
flag_ui_no_validation: false,
// -- Networking Options
flag_no_network: false,
flag_warp: true,
flag_port: 30303u16,
flag_min_peers: 25u16,
@@ -530,7 +527,7 @@ mod tests {
flag_snapshot_peers: 0u16,
flag_allow_ips: "all".into(),
flag_nat: "any".into(),
flag_network_id: Some("0x1".into()),
flag_network_id: Some(1),
flag_bootnodes: Some("".into()),
flag_no_discovery: false,
flag_node_key: None,
@@ -543,13 +540,13 @@ mod tests {
flag_jsonrpc_port: 8545u16,
flag_jsonrpc_interface: "local".into(),
flag_jsonrpc_cors: Some("null".into()),
flag_jsonrpc_apis: "web3,eth,net,ethcore,traces,rpc,personal_safe".into(),
flag_jsonrpc_apis: "web3,eth,net,parity,traces,rpc".into(),
flag_jsonrpc_hosts: "none".into(),
// IPC
flag_no_ipc: false,
flag_ipc_path: "$HOME/.parity/jsonrpc.ipc".into(),
flag_ipc_apis: "web3,eth,net,ethcore,traces,rpc,personal_safe".into(),
flag_ipc_apis: "web3,eth,net,parity,parity_accounts,personal,traces,rpc".into(),
// DAPPS
flag_no_dapps: false,
@@ -683,7 +680,7 @@ mod tests {
password: Some(vec!["passwdfile path".into()]),
keys_iterations: None,
}),
signer: Some(Signer {
ui: Some(Ui {
force: None,
disable: Some(true),
port: None,

View File

@@ -18,11 +18,12 @@ Usage:
Operating Options:
--mode MODE Set the operating mode. MODE can be one of:
last - Uses the last-used mode, active if none.
active - Parity continuously syncs the chain.
passive - Parity syncs initially, then sleeps and
wakes regularly to resync.
dark - Parity syncs only when an external interface
is active. (default: {flag_mode}).
dark - Parity syncs only when the RPC is active.
offline - Parity doesn't sync. (default: {flag_mode}).
--mode-timeout SECS Specify the number of seconds before inactivity
timeout occurs when mode is dark or passive
(default: {flag_mode_timeout}).
@@ -31,8 +32,8 @@ Operating Options:
(default: {flag_mode_alarm}).
--chain CHAIN Specify the blockchain type. CHAIN may be either a
JSON chain specification file or olympic, frontier,
homestead, mainnet, morden, classic, expanse or
testnet (default: {flag_chain}).
homestead, mainnet, morden, classic, expanse,
testnet or dev (default: {flag_chain}).
-d --db-path PATH Specify the database & configuration directory path
(default: {flag_db_path}).
--keys-path PATH Specify the path for JSON key files to be found
@@ -42,31 +43,31 @@ Operating Options:
Account Options:
--unlock ACCOUNTS Unlock ACCOUNTS for the duration of the execution.
ACCOUNTS is a comma-delimited list of addresses.
Implies --no-signer. (default: {flag_unlock:?})
Implies --no-ui. (default: {flag_unlock:?})
--password FILE Provide a file containing a password for unlocking
an account. Leading and trailing whitespace is trimmed.
(default: {flag_password:?})
--keys-iterations NUM Specify the number of iterations to use when
deriving key from the password (bigger is more
secure) (default: {flag_keys_iterations}).
--force-signer Enable Trusted Signer WebSocket endpoint used by
Signer UIs, even when --unlock is in use.
(default: ${flag_force_signer})
--no-signer Disable Trusted Signer WebSocket endpoint used by
Signer UIs. (default: ${flag_no_signer})
--signer-port PORT Specify the port of Trusted Signer server
(default: {flag_signer_port}).
--signer-interface IP Specify the hostname portion of the Trusted Signer
UI Options:
--force-ui Enable Trusted UI WebSocket endpoint,
even when --unlock is in use. (default: ${flag_force_ui})
--no-ui Disable Trusted UI WebSocket endpoint.
(default: ${flag_no_ui})
--ui-port PORT Specify the port of Trusted UI server
(default: {flag_ui_port}).
--ui-interface IP Specify the hostname portion of the Trusted UI
server, IP should be an interface's IP address,
or local (default: {flag_signer_interface}).
--signer-path PATH Specify directory where Signer UIs tokens should
be stored. (default: {flag_signer_path})
--signer-no-validation Disable Origin and Host headers validation for
Trusted Signer. WARNING: INSECURE. Used only for
development. (default: {flag_signer_no_validation})
or local (default: {flag_ui_interface}).
--ui-path PATH Specify directory where Trusted UIs tokens should
be stored. (default: {flag_ui_path})
--ui-no-validation Disable Origin and Host headers validation for
Trusted UI. WARNING: INSECURE. Used only for
development. (default: {flag_ui_no_validation})
Networking Options:
--no-network Disable p2p networking. (default: {flag_no_network})
--warp Enable syncing from the snapshot over the network. (default: {flag_warp})
--port PORT Override the port on which the node should listen
(default: {flag_port}).
@@ -107,7 +108,7 @@ API and Console Options:
--jsonrpc-apis APIS Specify the APIs available through the JSONRPC
interface. APIS is a comma-delimited list of API
name. Possible name are web3, eth, net, personal,
ethcore, ethcore_set, traces, rpc, personal_safe.
parity, parity_set, traces, rpc, parity_accounts.
(default: {flag_jsonrpc_apis}).
--jsonrpc-hosts HOSTS List of allowed Host header values. This option will
validate the Host header sent by the browser, it
@@ -284,7 +285,7 @@ Legacy Options:
--geth Run in Geth-compatibility mode. Sets the IPC path
to be the same as Geth's. Overrides the --ipc-path
and --ipcpath options. Alters RPCs to reflect Geth
bugs.
bugs. Includes the personal_ RPC by default.
--testnet Geth-compatible testnet mode. Equivalent to --chain
testnet --keys-path $HOME/parity/testnet-keys.
Overrides the --keys-path option.

View File

@@ -5,5 +5,6 @@ License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
By Wood/Paronyan/Kotewicz/Drwięga/Volf.
By Wood/Paronyan/Kotewicz/Drwięga/Volf
Habermeier/Czaban/Greeff/Gotchac/Redmann

View File

@@ -23,7 +23,7 @@ use cli::{Args, ArgsError};
use util::{Hashable, U256, Uint, Bytes, version_data, Secret, Address};
use util::log::Colour;
use ethsync::{NetworkConfiguration, is_valid_node_url, AllowIP};
use ethcore::client::{VMType, Mode};
use ethcore::client::VMType;
use ethcore::miner::{MinerOptions, Banning};
use rpc::{IpcConfiguration, HttpConfiguration};
@@ -35,7 +35,7 @@ use params::{ResealPolicy, AccountsConfig, GasPricerConfig, MinerExtras};
use ethcore_logger::Config as LogConfig;
use dir::Directories;
use dapps::Configuration as DappsConfiguration;
use signer::Configuration as SignerConfiguration;
use signer::{Configuration as SignerConfiguration, SignerCommand};
use run::RunCmd;
use blockchain::{BlockchainCmd, ImportBlockchain, ExportBlockchain, DataFormat};
use presale::ImportWallet;
@@ -49,11 +49,16 @@ pub enum Cmd {
Account(AccountCmd),
ImportPresaleWallet(ImportWallet),
Blockchain(BlockchainCmd),
SignerToken(String),
SignerToken(SignerCommand),
Snapshot(SnapshotCommand),
Hash(Option<String>),
}
pub struct Execute {
pub logger: LogConfig,
pub cmd: Cmd,
}
#[derive(Debug, PartialEq)]
pub struct Configuration {
pub args: Args,
@@ -70,28 +75,27 @@ impl Configuration {
Ok(config)
}
pub fn into_command(self) -> Result<Cmd, String> {
pub fn into_command(self) -> Result<Execute, String> {
let dirs = self.directories();
let pruning = try!(self.args.flag_pruning.parse());
let pruning_history = self.args.flag_pruning_history;
let vm_type = try!(self.vm_type());
let mode = try!(to_mode(&self.args.flag_mode, self.args.flag_mode_timeout, self.args.flag_mode_alarm));
let mode = match self.args.flag_mode.as_ref() { "last" => None, mode => Some(try!(to_mode(&mode, self.args.flag_mode_timeout, self.args.flag_mode_alarm))), };
let miner_options = try!(self.miner_options());
let logger_config = self.logger_config();
let http_conf = try!(self.http_config());
let ipc_conf = try!(self.ipc_config());
let net_conf = try!(self.net_config());
let network_id = try!(self.network_id());
let network_id = self.network_id();
let cache_config = self.cache_config();
let spec = try!(self.chain().parse());
let tracing = try!(self.args.flag_tracing.parse());
let fat_db = try!(self.args.flag_fat_db.parse());
let compaction = try!(self.args.flag_db_compaction.parse());
let wal = !self.args.flag_fast_and_loose;
let enable_network = self.enable_network(&mode);
let warp_sync = self.args.flag_warp;
let geth_compatibility = self.args.flag_geth;
let signer_port = self.signer_port();
let ui_address = self.ui_port().map(|port| (self.ui_interface(), port));
let dapps_conf = self.dapps_config();
let signer_conf = self.signer_config();
let format = try!(self.format());
@@ -99,7 +103,9 @@ impl Configuration {
let cmd = if self.args.flag_version {
Cmd::Version
} else if self.args.cmd_signer && self.args.cmd_new_token {
Cmd::SignerToken(dirs.signer)
Cmd::SignerToken(SignerCommand {
path: dirs.signer
})
} else if self.args.cmd_tools && self.args.cmd_hash {
Cmd::Hash(self.args.arg_file)
} else if self.args.cmd_account {
@@ -141,7 +147,6 @@ impl Configuration {
} else if self.args.cmd_import {
let import_cmd = ImportBlockchain {
spec: spec,
logger_config: logger_config,
cache_config: cache_config,
dirs: dirs,
file_path: self.args.arg_file.clone(),
@@ -150,17 +155,16 @@ impl Configuration {
pruning_history: pruning_history,
compaction: compaction,
wal: wal,
mode: mode,
tracing: tracing,
fat_db: fat_db,
vm_type: vm_type,
check_seal: !self.args.flag_no_seal_check,
with_color: logger_config.color,
};
Cmd::Blockchain(BlockchainCmd::Import(import_cmd))
} else if self.args.cmd_export {
let export_cmd = ExportBlockchain {
spec: spec,
logger_config: logger_config,
cache_config: cache_config,
dirs: dirs,
file_path: self.args.arg_file.clone(),
@@ -169,7 +173,6 @@ impl Configuration {
pruning_history: pruning_history,
compaction: compaction,
wal: wal,
mode: mode,
tracing: tracing,
fat_db: fat_db,
from_block: try!(to_block_id(&self.args.flag_from)),
@@ -184,8 +187,6 @@ impl Configuration {
spec: spec,
pruning: pruning,
pruning_history: pruning_history,
logger_config: logger_config,
mode: mode,
tracing: tracing,
fat_db: fat_db,
compaction: compaction,
@@ -202,8 +203,6 @@ impl Configuration {
spec: spec,
pruning: pruning,
pruning_history: pruning_history,
logger_config: logger_config,
mode: mode,
tracing: tracing,
fat_db: fat_db,
compaction: compaction,
@@ -227,7 +226,7 @@ impl Configuration {
pruning: pruning,
pruning_history: pruning_history,
daemon: daemon,
logger_config: logger_config,
logger_config: logger_config.clone(),
miner_options: miner_options,
http_conf: http_conf,
ipc_conf: ipc_conf,
@@ -242,10 +241,9 @@ impl Configuration {
compaction: compaction,
wal: wal,
vm_type: vm_type,
enable_network: enable_network,
warp_sync: warp_sync,
geth_compatibility: geth_compatibility,
signer_port: signer_port,
ui_address: ui_address,
net_settings: self.network_settings(),
dapps_conf: dapps_conf,
signer_conf: signer_conf,
@@ -258,14 +256,10 @@ impl Configuration {
Cmd::Run(run_cmd)
};
Ok(cmd)
}
fn enable_network(&self, mode: &Mode) -> bool {
match *mode {
Mode::Dark(_) => false,
_ => !self.args.flag_no_network,
}
Ok(Execute {
logger: logger_config,
cmd: cmd,
})
}
fn vm_type(&self) -> Result<VMType, String> {
@@ -402,11 +396,11 @@ impl Configuration {
fn signer_config(&self) -> SignerConfiguration {
SignerConfiguration {
enabled: self.signer_enabled(),
port: self.args.flag_signer_port,
interface: self.signer_interface(),
enabled: self.ui_enabled(),
port: self.args.flag_ui_port,
interface: self.ui_interface(),
signer_path: self.directories().signer,
skip_origin_validation: self.args.flag_signer_no_validation,
skip_origin_validation: self.args.flag_ui_no_validation,
}
}
@@ -510,16 +504,19 @@ impl Configuration {
Ok(ret)
}
fn network_id(&self) -> Result<Option<U256>, String> {
let net_id = self.args.flag_network_id.as_ref().or(self.args.flag_networkid.as_ref());
match net_id {
Some(id) => Ok(Some(try!(to_u256(id)))),
None => Ok(None),
}
fn network_id(&self) -> Option<usize> {
self.args.flag_network_id.or(self.args.flag_networkid)
}
fn rpc_apis(&self) -> String {
self.args.flag_rpcapi.clone().unwrap_or(self.args.flag_jsonrpc_apis.clone())
let mut apis = self.args.flag_rpcapi.clone().unwrap_or(self.args.flag_jsonrpc_apis.clone());
if self.args.flag_geth {
if !apis.is_empty() {
apis.push_str(",");
}
apis.push_str("personal");
}
apis
}
fn rpc_cors(&self) -> Option<Vec<String>> {
@@ -551,7 +548,16 @@ impl Configuration {
let conf = IpcConfiguration {
enabled: !(self.args.flag_ipcdisable || self.args.flag_ipc_off || self.args.flag_no_ipc),
socket_addr: self.ipc_path(),
apis: try!(self.args.flag_ipcapi.clone().unwrap_or(self.args.flag_ipc_apis.clone()).parse()),
apis: {
let mut apis = self.args.flag_ipcapi.clone().unwrap_or(self.args.flag_ipc_apis.clone());
if self.args.flag_geth {
if !apis.is_empty() {
apis.push_str(",");
}
apis.push_str("personal");
}
try!(apis.parse())
},
};
Ok(conf)
@@ -595,7 +601,7 @@ impl Configuration {
);
let dapps_path = replace_home(&self.args.flag_dapps_path);
let signer_path = replace_home(&self.args.flag_signer_path);
let ui_path = replace_home(&self.args.flag_ui_path);
if self.args.flag_geth && !cfg!(windows) {
let geth_root = if self.args.flag_testnet { path::ethereum::test() } else { path::ethereum::default() };
@@ -616,7 +622,7 @@ impl Configuration {
keys: keys_path,
db: db_path,
dapps: dapps_path,
signer: signer_path,
signer: ui_path,
}
}
@@ -628,16 +634,16 @@ impl Configuration {
}
}
fn signer_port(&self) -> Option<u16> {
if !self.signer_enabled() {
fn ui_port(&self) -> Option<u16> {
if !self.ui_enabled() {
None
} else {
Some(self.args.flag_signer_port)
Some(self.args.flag_ui_port)
}
}
fn signer_interface(&self) -> String {
match self.args.flag_signer_interface.as_str() {
fn ui_interface(&self) -> String {
match self.args.flag_ui_interface.as_str() {
"local" => "127.0.0.1",
x => x,
}.into()
@@ -662,16 +668,16 @@ impl Configuration {
!self.args.flag_dapps_off && !self.args.flag_no_dapps && cfg!(feature = "dapps")
}
fn signer_enabled(&self) -> bool {
if self.args.flag_force_signer {
fn ui_enabled(&self) -> bool {
if self.args.flag_force_ui {
return true;
}
let signer_disabled = self.args.flag_unlock.is_some() ||
let ui_disabled = self.args.flag_unlock.is_some() ||
self.args.flag_geth ||
self.args.flag_no_signer;
self.args.flag_no_ui;
!signer_disabled
!ui_disabled
}
}
@@ -684,7 +690,7 @@ mod tests {
use ethcore::miner::{MinerOptions, PrioritizationStrategy};
use helpers::{replace_home, default_network_config};
use run::RunCmd;
use signer::Configuration as SignerConfiguration;
use signer::{Configuration as SignerConfiguration, SignerCommand};
use blockchain::{BlockchainCmd, ImportBlockchain, ExportBlockchain, DataFormat};
use presale::ImportWallet;
use account::{AccountCmd, NewAccount, ImportAccounts};
@@ -705,14 +711,14 @@ mod tests {
fn test_command_version() {
let args = vec!["parity", "--version"];
let conf = parse(&args);
assert_eq!(conf.into_command().unwrap(), Cmd::Version);
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::Account(AccountCmd::New(NewAccount {
assert_eq!(conf.into_command().unwrap().cmd, Cmd::Account(AccountCmd::New(NewAccount {
iterations: 10240,
path: replace_home("$HOME/.parity/keys"),
password_file: None,
@@ -723,16 +729,16 @@ mod tests {
fn test_command_account_list() {
let args = vec!["parity", "account", "list"];
let conf = parse(&args);
assert_eq!(conf.into_command().unwrap(), Cmd::Account(
AccountCmd::List(replace_home("$HOME/.parity/keys")))
);
assert_eq!(conf.into_command().unwrap().cmd, Cmd::Account(
AccountCmd::List(replace_home("$HOME/.parity/keys")),
));
}
#[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::Account(AccountCmd::Import(ImportAccounts {
assert_eq!(conf.into_command().unwrap().cmd, Cmd::Account(AccountCmd::Import(ImportAccounts {
from: vec!["my_dir".into(), "another_dir".into()],
to: replace_home("$HOME/.parity/keys"),
})));
@@ -742,7 +748,7 @@ mod tests {
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::ImportPresaleWallet(ImportWallet {
assert_eq!(conf.into_command().unwrap().cmd, Cmd::ImportPresaleWallet(ImportWallet {
iterations: 10240,
path: replace_home("$HOME/.parity/keys"),
wallet_path: "my_wallet.json".into(),
@@ -754,9 +760,8 @@ mod tests {
fn test_command_blockchain_import() {
let args = vec!["parity", "import", "blockchain.json"];
let conf = parse(&args);
assert_eq!(conf.into_command().unwrap(), Cmd::Blockchain(BlockchainCmd::Import(ImportBlockchain {
assert_eq!(conf.into_command().unwrap().cmd, Cmd::Blockchain(BlockchainCmd::Import(ImportBlockchain {
spec: Default::default(),
logger_config: Default::default(),
cache_config: Default::default(),
dirs: Default::default(),
file_path: Some("blockchain.json".into()),
@@ -765,11 +770,11 @@ mod tests {
pruning_history: 64,
compaction: Default::default(),
wal: true,
mode: Default::default(),
tracing: Default::default(),
fat_db: Default::default(),
vm_type: VMType::Interpreter,
check_seal: true,
with_color: !cfg!(windows),
})));
}
@@ -777,9 +782,8 @@ mod tests {
fn test_command_blockchain_export() {
let args = vec!["parity", "export", "blockchain.json"];
let conf = parse(&args);
assert_eq!(conf.into_command().unwrap(), Cmd::Blockchain(BlockchainCmd::Export(ExportBlockchain {
assert_eq!(conf.into_command().unwrap().cmd, Cmd::Blockchain(BlockchainCmd::Export(ExportBlockchain {
spec: Default::default(),
logger_config: Default::default(),
cache_config: Default::default(),
dirs: Default::default(),
file_path: Some("blockchain.json".into()),
@@ -788,7 +792,6 @@ mod tests {
format: Default::default(),
compaction: Default::default(),
wal: true,
mode: Default::default(),
tracing: Default::default(),
fat_db: Default::default(),
from_block: BlockID::Number(1),
@@ -801,9 +804,8 @@ mod tests {
fn test_command_blockchain_export_with_custom_format() {
let args = vec!["parity", "export", "--format", "hex", "blockchain.json"];
let conf = parse(&args);
assert_eq!(conf.into_command().unwrap(), Cmd::Blockchain(BlockchainCmd::Export(ExportBlockchain {
assert_eq!(conf.into_command().unwrap().cmd, Cmd::Blockchain(BlockchainCmd::Export(ExportBlockchain {
spec: Default::default(),
logger_config: Default::default(),
cache_config: Default::default(),
dirs: Default::default(),
file_path: Some("blockchain.json".into()),
@@ -812,7 +814,6 @@ mod tests {
format: Some(DataFormat::Hex),
compaction: Default::default(),
wal: true,
mode: Default::default(),
tracing: Default::default(),
fat_db: Default::default(),
from_block: BlockID::Number(1),
@@ -826,14 +827,16 @@ mod tests {
let args = vec!["parity", "signer", "new-token"];
let conf = parse(&args);
let expected = replace_home("$HOME/.parity/signer");
assert_eq!(conf.into_command().unwrap(), Cmd::SignerToken(expected));
assert_eq!(conf.into_command().unwrap().cmd, Cmd::SignerToken(SignerCommand {
path: expected,
}));
}
#[test]
fn test_run_cmd() {
let args = vec!["parity"];
let conf = parse(&args);
assert_eq!(conf.into_command().unwrap(), Cmd::Run(RunCmd {
assert_eq!(conf.into_command().unwrap().cmd, Cmd::Run(RunCmd {
cache_config: Default::default(),
dirs: Default::default(),
spec: Default::default(),
@@ -855,9 +858,8 @@ mod tests {
compaction: Default::default(),
wal: true,
vm_type: Default::default(),
enable_network: true,
geth_compatibility: false,
signer_port: Some(8180),
ui_address: Some(("127.0.0.1".into(), 8180)),
net_settings: Default::default(),
dapps_conf: Default::default(),
signer_conf: Default::default(),
@@ -980,11 +982,11 @@ mod tests {
// when
let conf0 = parse(&["parity", "--geth"]);
let conf1 = parse(&["parity", "--geth", "--force-signer"]);
let conf1 = parse(&["parity", "--geth", "--force-ui"]);
// then
assert_eq!(conf0.signer_enabled(), false);
assert_eq!(conf1.signer_enabled(), true);
assert_eq!(conf0.ui_enabled(), false);
assert_eq!(conf1.ui_enabled(), true);
}
#[test]
@@ -995,7 +997,7 @@ mod tests {
let conf0 = parse(&["parity", "--unlock", "0x0"]);
// then
assert_eq!(conf0.signer_enabled(), false);
assert_eq!(conf0.ui_enabled(), false);
}
#[test]
@@ -1003,10 +1005,10 @@ mod tests {
// given
// when
let conf0 = parse(&["parity", "--signer-path", "signer"]);
let conf1 = parse(&["parity", "--signer-path", "signer", "--signer-no-validation"]);
let conf2 = parse(&["parity", "--signer-path", "signer", "--signer-port", "3123"]);
let conf3 = parse(&["parity", "--signer-path", "signer", "--signer-interface", "test"]);
let conf0 = parse(&["parity", "--ui-path", "signer"]);
let conf1 = parse(&["parity", "--ui-path", "signer", "--ui-no-validation"]);
let conf2 = parse(&["parity", "--ui-path", "signer", "--ui-port", "3123"]);
let conf3 = parse(&["parity", "--ui-path", "signer", "--ui-interface", "test"]);
// then
assert_eq!(conf0.signer_config(), SignerConfiguration {

View File

@@ -58,7 +58,7 @@ pub fn new(configuration: Configuration, deps: Dependencies) -> Result<Option<We
return Ok(None);
}
let signer_port = deps.apis.signer_service.port();
let signer_address = deps.apis.signer_service.address();
let url = format!("{}:{}", configuration.interface, configuration.port);
let addr = try!(url.parse().map_err(|_| format!("Invalid Webapps listen host/port given: {}", url)));
@@ -73,7 +73,7 @@ pub fn new(configuration: Configuration, deps: Dependencies) -> Result<Option<We
(username.to_owned(), password)
});
Ok(Some(try!(setup_dapps_server(deps, configuration.dapps_path, &addr, configuration.hosts, auth, signer_port))))
Ok(Some(try!(setup_dapps_server(deps, configuration.dapps_path, &addr, configuration.hosts, auth, signer_address))))
}
pub use self::server::WebappServer;
@@ -91,7 +91,7 @@ mod server {
_url: &SocketAddr,
_allowed_hosts: Option<Vec<String>>,
_auth: Option<(String, String)>,
_signer_port: Option<u16>,
_signer_address: Option<(String, u16)>,
) -> Result<WebappServer, String> {
Err("Your Parity version has been compiled without WebApps support.".into())
}
@@ -120,7 +120,7 @@ mod server {
url: &SocketAddr,
allowed_hosts: Option<Vec<String>>,
auth: Option<(String, String)>,
signer_port: Option<u16>,
signer_address: Option<(String, u16)>,
) -> Result<WebappServer, String> {
use ethcore_dapps as dapps;
@@ -131,7 +131,7 @@ mod server {
let sync = deps.sync.clone();
let client = deps.client.clone();
server.with_sync_status(Arc::new(move || is_major_importing(Some(sync.status().state), client.queue_info())));
server.with_signer_port(signer_port);
server.with_signer_address(signer_address);
let server = rpc_apis::setup_rpc(server, deps.apis.clone(), rpc_apis::ApiSet::UnsafeContext);
let start_result = match auth {

View File

@@ -15,9 +15,8 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::{io, env};
use std::io::{Write, Read, BufReader, BufRead};
use std::io::{Write, BufReader, BufRead};
use std::time::Duration;
use std::path::Path;
use std::fs::File;
use util::{clean_0x, U256, Uint, Address, path, CompactionProfile};
use util::journaldb::Algorithm;
@@ -46,7 +45,7 @@ fn to_seconds(s: &str) -> Result<u64, String> {
"hourly" | "1hour" | "1 hour" | "hour" => Ok(60 * 60),
"daily" | "1day" | "1 day" | "day" => Ok(24 * 60 * 60),
x if x.ends_with("seconds") => x[0..x.len() - 7].parse().map_err(bad),
x if x.ends_with("minutes") => x[0..x.len() -7].parse::<u64>().map_err(bad).map(|x| x * 60),
x if x.ends_with("minutes") => x[0..x.len() - 7].parse::<u64>().map_err(bad).map(|x| x * 60),
x if x.ends_with("hours") => x[0..x.len() - 5].parse::<u64>().map_err(bad).map(|x| x * 60 * 60),
x if x.ends_with("days") => x[0..x.len() - 4].parse::<u64>().map_err(bad).map(|x| x * 24 * 60 * 60),
x => x.parse().map_err(bad),
@@ -58,7 +57,8 @@ pub fn to_mode(s: &str, timeout: u64, alarm: u64) -> Result<Mode, String> {
"active" => Ok(Mode::Active),
"passive" => Ok(Mode::Passive(Duration::from_secs(timeout), Duration::from_secs(alarm))),
"dark" => Ok(Mode::Dark(Duration::from_secs(timeout))),
_ => Err(format!("{}: Invalid address for --mode. Must be one of active, passive or dark.", s)),
"offline" => Ok(Mode::Off),
_ => Err(format!("{}: Invalid value for --mode. Must be one of active, passive, dark or offline.", s)),
}
}
@@ -278,17 +278,18 @@ pub fn execute_upgrades(
/// Prompts user asking for password.
pub fn password_prompt() -> Result<String, String> {
use rpassword::read_password;
const STDIN_ERROR: &'static str = "Unable to ask for password on non-interactive terminal.";
println!("Please note that password is NOT RECOVERABLE.");
print!("Type password: ");
flush_stdout();
let password = read_password().unwrap();
let password = try!(read_password().map_err(|_| STDIN_ERROR.to_owned()));
print!("Repeat password: ");
flush_stdout();
let password_repeat = read_password().unwrap();
let password_repeat = try!(read_password().map_err(|_| STDIN_ERROR.to_owned()));
if password != password_repeat {
return Err("Passwords do not match!".into());
@@ -298,13 +299,11 @@ pub fn password_prompt() -> Result<String, String> {
}
/// Read a password from password file.
pub fn password_from_file<P>(path: P) -> Result<String, String> where P: AsRef<Path> {
let mut file = try!(File::open(path).map_err(|_| "Unable to open password file."));
let mut file_content = String::new();
match file.read_to_string(&mut file_content) {
Ok(_) => Ok(file_content.trim().into()),
Err(_) => Err("Unable to read password file.".into()),
}
pub fn password_from_file(path: String) -> Result<String, String> {
let passwords = try!(passwords_from_files(vec![path]));
// use only first password from the file
passwords.get(0).map(String::to_owned)
.ok_or_else(|| "Password file seems to be empty.".to_owned())
}
/// Reads passwords from files. Treats each line as a separate password.
@@ -313,10 +312,11 @@ pub fn passwords_from_files(files: Vec<String>) -> Result<Vec<String>, String> {
let file = try!(File::open(filename).map_err(|_| format!("{} Unable to read password file. Ensure it exists and permissions are correct.", filename)));
let reader = BufReader::new(&file);
let lines = reader.lines()
.map(|l| l.unwrap())
.filter_map(|l| l.ok())
.map(|pwd| pwd.trim().to_owned())
.collect::<Vec<String>>();
Ok(lines)
}).collect::<Result<Vec<Vec<String>>, String>>();
}).collect::<Result<Vec<Vec<String>>, String>>();
Ok(try!(passwords).into_iter().flat_map(|x| x).collect())
}
@@ -417,7 +417,20 @@ mod tests {
let path = RandomTempPath::new();
let mut file = File::create(path.as_path()).unwrap();
file.write_all(b"a bc ").unwrap();
assert_eq!(password_from_file(path).unwrap().as_bytes(), b"a bc");
assert_eq!(password_from_file(path.as_str().into()).unwrap().as_bytes(), b"a bc");
}
#[test]
fn test_password_multiline() {
let path = RandomTempPath::new();
let mut file = File::create(path.as_path()).unwrap();
file.write_all(br#" password with trailing whitespace
those passwords should be
ignored
but the first password is trimmed
"#).unwrap();
assert_eq!(&password_from_file(path.as_str().into()).unwrap(), "password with trailing whitespace");
}
#[test]

View File

@@ -114,12 +114,13 @@ mod user_defaults;
mod stratum;
use std::{process, env};
use std::io::BufReader;
use std::io::{self as stdio, BufReader, Write};
use std::fs::File;
use util::sha3::sha3;
use cli::Args;
use configuration::{Cmd, Configuration};
use configuration::{Cmd, Execute, Configuration};
use deprecated::find_deprecated;
use ethcore_logger::setup_log;
fn print_hash_of(maybe_file: Option<String>) -> Result<String, String> {
if let Some(file) = maybe_file {
@@ -131,10 +132,12 @@ fn print_hash_of(maybe_file: Option<String>) -> Result<String, String> {
}
}
fn execute(command: Cmd) -> Result<String, String> {
match command {
fn execute(command: Execute) -> Result<String, String> {
let logger = setup_log(&command.logger).expect("Logger is initialized only once; qed");
match command.cmd {
Cmd::Run(run_cmd) => {
try!(run::execute(run_cmd));
try!(run::execute(run_cmd, logger));
Ok("".into())
},
Cmd::Version => Ok(Args::print_version()),
@@ -142,7 +145,7 @@ fn execute(command: Cmd) -> Result<String, String> {
Cmd::Account(account_cmd) => account::execute(account_cmd),
Cmd::ImportPresaleWallet(presale_cmd) => presale::execute(presale_cmd),
Cmd::Blockchain(blockchain_cmd) => blockchain::execute(blockchain_cmd),
Cmd::SignerToken(path) => signer::new_token(path),
Cmd::SignerToken(signer_cmd) => signer::execute(signer_cmd),
Cmd::Snapshot(snapshot_cmd) => snapshot::execute(snapshot_cmd),
}
}
@@ -198,7 +201,7 @@ fn sync_main() -> bool {
fn main() {
// Always print backtrace on panic.
::std::env::set_var("RUST_BACKTRACE", "1");
if sync_main() {
return;
}
@@ -210,7 +213,7 @@ fn main() {
info!("{}", result);
},
Err(err) => {
info!("{}", err);
writeln!(&mut stdio::stderr(), "{}", err).expect("StdErr available; qed");
process::exit(1);
}
}

View File

@@ -20,6 +20,7 @@ use util::{Address, U256, version_data};
use util::journaldb::Algorithm;
use ethcore::spec::Spec;
use ethcore::ethereum;
use ethcore::client::Mode;
use ethcore::miner::{GasPricer, GasPriceCalibratorOptions};
use user_defaults::UserDefaults;
@@ -30,6 +31,7 @@ pub enum SpecType {
Olympic,
Classic,
Expanse,
Dev,
Custom(String),
}
@@ -49,6 +51,7 @@ impl str::FromStr for SpecType {
"morden" | "testnet" => SpecType::Testnet,
"olympic" => SpecType::Olympic,
"expanse" => SpecType::Expanse,
"dev" => SpecType::Dev,
other => SpecType::Custom(other.into()),
};
Ok(spec)
@@ -63,6 +66,7 @@ impl SpecType {
SpecType::Olympic => Ok(ethereum::new_olympic()),
SpecType::Classic => Ok(ethereum::new_classic()),
SpecType::Expanse => Ok(ethereum::new_expanse()),
SpecType::Dev => Ok(Spec::new_instant()),
SpecType::Custom(ref filename) => {
let file = try!(fs::File::open(filename).map_err(|_| "Could not load specification file."));
Spec::load(file)
@@ -264,6 +268,10 @@ pub fn fatdb_switch_to_bool(switch: Switch, user_defaults: &UserDefaults, algori
result
}
pub fn mode_switch_to_bool(switch: Option<Mode>, user_defaults: &UserDefaults) -> Result<Mode, String> {
Ok(switch.unwrap_or(user_defaults.mode.clone()))
}
#[cfg(test)]
mod tests {
use util::journaldb::Algorithm;

View File

@@ -63,7 +63,7 @@ impl Default for IpcConfiguration {
IpcConfiguration {
enabled: true,
socket_addr: parity_ipc_path("$HOME/.parity/jsonrpc.ipc"),
apis: ApiSet::UnsafeContext,
apis: ApiSet::IpcContext,
}
}
}

View File

@@ -31,15 +31,25 @@ pub use ethcore_rpc::SignerService;
#[derive(Debug, PartialEq, Clone, Eq, Hash)]
pub enum Api {
/// Web3 (Safe)
Web3,
/// Net (Safe)
Net,
/// Eth (Safe)
Eth,
PersonalSafe,
PersonalAccounts,
/// Geth-compatible "personal" API (DEPRECATED; only used in `--geth` mode.)
Personal,
/// Signer - Confirm transactions in Signer (UNSAFE: Passwords, List of transactions)
Signer,
Ethcore,
EthcoreSet,
/// Parity - Custom extensions (Safe)
Parity,
/// Parity Accounts extensions (UNSAFE: Passwords, Side Effects (new account))
ParityAccounts,
/// Parity - Set methods (UNSAFE: Side Effects affecting node operation)
ParitySet,
/// Traces (Safe)
Traces,
/// Rpc (Safe)
Rpc,
}
@@ -53,11 +63,11 @@ impl FromStr for Api {
"web3" => Ok(Web3),
"net" => Ok(Net),
"eth" => Ok(Eth),
"personal" => Ok(PersonalAccounts),
"personal_safe" => Ok(PersonalSafe),
"personal" => Ok(Personal),
"signer" => Ok(Signer),
"ethcore" => Ok(Ethcore),
"ethcore_set" => Ok(EthcoreSet),
"parity" => Ok(Parity),
"parity_accounts" => Ok(ParityAccounts),
"parity_set" => Ok(ParitySet),
"traces" => Ok(Traces),
"rpc" => Ok(Rpc),
api => Err(format!("Unknown api: {}", api))
@@ -69,6 +79,7 @@ impl FromStr for Api {
pub enum ApiSet {
SafeContext,
UnsafeContext,
IpcContext,
List(HashSet<Api>),
}
@@ -108,6 +119,7 @@ pub struct Dependencies {
pub settings: Arc<NetworkSettings>,
pub net_service: Arc<ManageNetwork>,
pub geth_compatibility: bool,
pub dapps_interface: Option<String>,
pub dapps_port: Option<u16>,
}
@@ -118,11 +130,11 @@ fn to_modules(apis: &[Api]) -> BTreeMap<String, String> {
Api::Web3 => ("web3", "1.0"),
Api::Net => ("net", "1.0"),
Api::Eth => ("eth", "1.0"),
Api::PersonalSafe => ("personal_safe", "1.0"),
Api::PersonalAccounts => ("personal", "1.0"),
Api::Personal => ("personal", "1.0"),
Api::Signer => ("signer", "1.0"),
Api::Ethcore => ("ethcore", "1.0"),
Api::EthcoreSet => ("ethcore_set", "1.0"),
Api::Parity => ("parity", "1.0"),
Api::ParityAccounts => ("parity_accounts", "1.0"),
Api::ParitySet => ("parity_set", "1.0"),
Api::Traces => ("traces", "1.0"),
Api::Rpc => ("rpc", "1.0"),
};
@@ -133,20 +145,37 @@ fn to_modules(apis: &[Api]) -> BTreeMap<String, String> {
impl ApiSet {
pub fn list_apis(&self) -> HashSet<Api> {
let mut safe_list = vec![Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc]
.into_iter().collect();
match *self {
ApiSet::List(ref apis) => apis.clone(),
ApiSet::UnsafeContext => {
vec![Api::Web3, Api::Net, Api::Eth, Api::Ethcore, Api::Traces, Api::Rpc, Api::PersonalSafe]
.into_iter().collect()
ApiSet::UnsafeContext => safe_list,
ApiSet::IpcContext => {
safe_list.insert(Api::ParityAccounts);
safe_list
},
ApiSet::SafeContext => {
vec![Api::Web3, Api::Net, Api::Eth, Api::PersonalAccounts, Api::PersonalSafe, Api::Signer, Api::Ethcore, Api::EthcoreSet, Api::Traces, Api::Rpc]
.into_iter().collect()
safe_list.insert(Api::ParityAccounts);
safe_list.insert(Api::ParitySet);
safe_list.insert(Api::Signer);
safe_list
},
}
}
}
macro_rules! add_signing_methods {
($namespace:ident, $server:expr, $deps:expr) => {
let server = &$server;
let deps = &$deps;
if deps.signer_service.is_enabled() {
server.add_delegate($namespace::to_delegate(SigningQueueClient::new(&deps.signer_service, &deps.client, &deps.miner, &deps.secret_store)))
} else {
server.add_delegate($namespace::to_delegate(SigningUnsafeClient::new(&deps.client, &deps.secret_store, &deps.miner)))
}
}
}
pub fn setup_rpc<T: Extendable>(server: T, deps: Arc<Dependencies>, apis: ApiSet) -> T {
use ethcore_rpc::v1::*;
@@ -178,39 +207,40 @@ pub fn setup_rpc<T: Extendable>(server: T, deps: Arc<Dependencies>, apis: ApiSet
let filter_client = EthFilterClient::new(&deps.client, &deps.miner);
server.add_delegate(filter_client.to_delegate());
if deps.signer_service.is_enabled() {
server.add_delegate(EthSigningQueueClient::new(&deps.signer_service, &deps.client, &deps.miner, &deps.secret_store).to_delegate());
} else {
server.add_delegate(EthSigningUnsafeClient::new(&deps.client, &deps.secret_store, &deps.miner).to_delegate());
}
add_signing_methods!(EthSigning, server, deps);
},
Api::PersonalAccounts => {
server.add_delegate(PersonalAccountsClient::new(&deps.secret_store, &deps.client, &deps.miner, deps.geth_compatibility).to_delegate());
},
Api::PersonalSafe => {
server.add_delegate(PersonalClient::new(&deps.secret_store, &deps.client).to_delegate());
Api::Personal => {
server.add_delegate(PersonalClient::new(&deps.secret_store, &deps.client, &deps.miner, deps.geth_compatibility).to_delegate());
},
Api::Signer => {
server.add_delegate(SignerClient::new(&deps.secret_store, &deps.client, &deps.miner, &deps.signer_service).to_delegate());
},
Api::Ethcore => {
Api::Parity => {
let signer = match deps.signer_service.is_enabled() {
true => Some(deps.signer_service.clone()),
false => None,
};
server.add_delegate(EthcoreClient::new(
server.add_delegate(ParityClient::new(
&deps.client,
&deps.miner,
&deps.sync,
&deps.net_service,
&deps.secret_store,
deps.logger.clone(),
deps.settings.clone(),
signer,
deps.dapps_interface.clone(),
deps.dapps_port,
).to_delegate())
).to_delegate());
add_signing_methods!(EthSigning, server, deps);
add_signing_methods!(ParitySigning, server, deps);
},
Api::EthcoreSet => {
server.add_delegate(EthcoreSetClient::new(&deps.client, &deps.miner, &deps.net_service).to_delegate())
Api::ParityAccounts => {
server.add_delegate(ParityAccountsClient::new(&deps.secret_store, &deps.client).to_delegate());
},
Api::ParitySet => {
server.add_delegate(ParitySetClient::new(&deps.client, &deps.miner, &deps.net_service).to_delegate())
},
Api::Traces => {
server.add_delegate(TracesClient::new(&deps.client, &deps.miner).to_delegate())
@@ -233,11 +263,11 @@ mod test {
assert_eq!(Api::Web3, "web3".parse().unwrap());
assert_eq!(Api::Net, "net".parse().unwrap());
assert_eq!(Api::Eth, "eth".parse().unwrap());
assert_eq!(Api::PersonalAccounts, "personal".parse().unwrap());
assert_eq!(Api::PersonalSafe, "personal_safe".parse().unwrap());
assert_eq!(Api::Personal, "personal".parse().unwrap());
assert_eq!(Api::Signer, "signer".parse().unwrap());
assert_eq!(Api::Ethcore, "ethcore".parse().unwrap());
assert_eq!(Api::EthcoreSet, "ethcore_set".parse().unwrap());
assert_eq!(Api::Parity, "parity".parse().unwrap());
assert_eq!(Api::ParityAccounts, "parity_accounts".parse().unwrap());
assert_eq!(Api::ParitySet, "parity_set".parse().unwrap());
assert_eq!(Api::Traces, "traces".parse().unwrap());
assert_eq!(Api::Rpc, "rpc".parse().unwrap());
assert!("rp".parse::<Api>().is_err());
@@ -255,15 +285,34 @@ mod test {
#[test]
fn test_api_set_unsafe_context() {
let expected = vec![Api::Web3, Api::Net, Api::Eth, Api::Ethcore, Api::Traces, Api::Rpc, Api::PersonalSafe]
.into_iter().collect();
let expected = vec![
// make sure this list contains only SAFE methods
Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc
].into_iter().collect();
assert_eq!(ApiSet::UnsafeContext.list_apis(), expected);
}
#[test]
fn test_api_set_ipc_context() {
let expected = vec![
// safe
Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc,
// semi-safe
Api::ParityAccounts
].into_iter().collect();
assert_eq!(ApiSet::IpcContext.list_apis(), expected);
}
#[test]
fn test_api_set_safe_context() {
let expected = vec![Api::Web3, Api::Net, Api::Eth, Api::PersonalAccounts, Api::PersonalSafe, Api::Signer, Api::Ethcore, Api::EthcoreSet, Api::Traces, Api::Rpc]
.into_iter().collect();
let expected = vec![
// safe
Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc,
// semi-safe
Api::ParityAccounts,
// Unsafe
Api::ParitySet, Api::Signer,
].into_iter().collect();
assert_eq!(ApiSet::SafeContext.list_apis(), expected);
}
}

View File

@@ -15,13 +15,14 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::sync::{Arc, Mutex, Condvar};
use std::net::{TcpListener};
use ctrlc::CtrlC;
use fdlimit::raise_fd_limit;
use ethcore_logger::{Config as LogConfig, setup_log};
use ethcore_rpc::{NetworkSettings, is_major_importing};
use ethsync::NetworkConfiguration;
use util::{Colour, version, U256};
use util::{Colour, version, RotatingLogger};
use io::{MayPanic, ForwardPanic, PanicHandler};
use ethcore_logger::{Config as LogConfig};
use ethcore::client::{Mode, DatabaseCompactionProfile, VMType, ChainNotify, BlockChainClient};
use ethcore::service::ClientService;
use ethcore::account_provider::AccountProvider;
@@ -36,7 +37,7 @@ use dapps::WebappServer;
use io_handler::ClientIoHandler;
use params::{
SpecType, Pruning, AccountsConfig, GasPricerConfig, MinerExtras, Switch,
tracing_switch_to_bool, fatdb_switch_to_bool,
tracing_switch_to_bool, fatdb_switch_to_bool, mode_switch_to_bool
};
use helpers::{to_client_config, execute_upgrades, passwords_from_files};
use dir::Directories;
@@ -69,20 +70,19 @@ pub struct RunCmd {
pub http_conf: HttpConfiguration,
pub ipc_conf: IpcConfiguration,
pub net_conf: NetworkConfiguration,
pub network_id: Option<U256>,
pub network_id: Option<usize>,
pub warp_sync: bool,
pub acc_conf: AccountsConfig,
pub gas_pricer: GasPricerConfig,
pub miner_extras: MinerExtras,
pub mode: Mode,
pub mode: Option<Mode>,
pub tracing: Switch,
pub fat_db: Switch,
pub compaction: DatabaseCompactionProfile,
pub wal: bool,
pub vm_type: VMType,
pub enable_network: bool,
pub geth_compatibility: bool,
pub signer_port: Option<u16>,
pub ui_address: Option<(String, u16)>,
pub net_settings: NetworkSettings,
pub dapps_conf: dapps::Configuration,
pub signer_conf: signer::Configuration,
@@ -93,13 +93,19 @@ pub struct RunCmd {
pub check_seal: bool,
}
pub fn execute(cmd: RunCmd) -> Result<(), String> {
pub fn execute(cmd: RunCmd, logger: Arc<RotatingLogger>) -> Result<(), String> {
if cmd.ui && cmd.dapps_conf.enabled {
// Check if Parity is already running
let addr = format!("{}:{}", cmd.dapps_conf.interface, cmd.dapps_conf.port);
if !TcpListener::bind(&addr as &str).is_ok() {
url::open(&format!("http://{}:{}/", cmd.dapps_conf.interface, cmd.dapps_conf.port));
return Ok(());
}
}
// set up panic handler
let panic_handler = PanicHandler::new_in_arc();
// set up logger
let logger = try!(setup_log(&cmd.logger_config));
// increase max number of open files
raise_fd_limit();
@@ -130,6 +136,11 @@ pub fn execute(cmd: RunCmd) -> Result<(), String> {
// check if fatdb is on
let fat_db = try!(fatdb_switch_to_bool(cmd.fat_db, &user_defaults, algorithm));
// get the mode
let mode = try!(mode_switch_to_bool(cmd.mode, &user_defaults));
trace!(target: "mode", "mode is {:?}", mode);
let network_enabled = match &mode { &Mode::Dark(_) | &Mode::Off => false, _ => true, };
// prepare client and snapshot paths.
let client_path = db_dirs.client_path(algorithm);
let snapshot_path = db_dirs.snapshot_path();
@@ -155,6 +166,7 @@ pub fn execute(cmd: RunCmd) -> Result<(), String> {
false => "".to_owned(),
}
);
info!("Operating mode: {}", Colour::White.bold().paint(format!("{}", mode)));
// display warning about using experimental journaldb alorithm
if !algorithm.is_stable() {
@@ -189,7 +201,7 @@ pub fn execute(cmd: RunCmd) -> Result<(), String> {
// create client config
let client_config = to_client_config(
&cmd.cache_config,
cmd.mode,
mode,
tracing,
fat_db,
cmd.compaction,
@@ -241,7 +253,7 @@ pub fn execute(cmd: RunCmd) -> Result<(), String> {
service.add_notify(chain_notify.clone());
// start network
if cmd.enable_network {
if network_enabled {
chain_notify.start();
}
@@ -250,7 +262,7 @@ pub fn execute(cmd: RunCmd) -> Result<(), String> {
let deps_for_rpc_apis = Arc::new(rpc_apis::Dependencies {
signer_service: Arc::new(rpc_apis::SignerService::new(move || {
signer::generate_new_token(signer_path.clone()).map_err(|e| format!("{:?}", e))
}, cmd.signer_port)),
}, cmd.ui_address)),
snapshot: snapshot_service.clone(),
client: client.clone(),
sync: sync_provider.clone(),
@@ -262,6 +274,10 @@ pub fn execute(cmd: RunCmd) -> Result<(), String> {
settings: Arc::new(cmd.net_settings.clone()),
net_service: manage_network.clone(),
geth_compatibility: cmd.geth_compatibility,
dapps_interface: match cmd.dapps_conf.enabled {
true => Some(cmd.dapps_conf.interface.clone()),
false => None,
},
dapps_port: match cmd.dapps_conf.enabled {
true => Some(cmd.dapps_conf.port),
false => None,
@@ -314,6 +330,19 @@ pub fn execute(cmd: RunCmd) -> Result<(), String> {
});
service.register_io_handler(io_handler.clone()).expect("Error registering IO handler");
// save user defaults
user_defaults.pruning = algorithm;
user_defaults.tracing = tracing;
try!(user_defaults.save(&user_defaults_path));
let on_mode_change = move |mode: &Mode| {
user_defaults.mode = mode.clone();
let _ = user_defaults.save(&user_defaults_path); // discard failures - there's nothing we can do
};
// tell client how to save the default mode if it gets changed.
client.on_mode_change(on_mode_change);
// the watcher must be kept alive.
let _watcher = match cmd.no_periodic_snapshot {
true => None,
@@ -340,11 +369,6 @@ pub fn execute(cmd: RunCmd) -> Result<(), String> {
url::open(&format!("http://{}:{}/", cmd.dapps_conf.interface, cmd.dapps_conf.port));
}
// save user defaults
user_defaults.pruning = algorithm;
user_defaults.tracing = tracing;
try!(user_defaults.save(&user_defaults_path));
// Handle exit
wait_for_exit(panic_handler, http_server, ipc_server, dapps_server, signer_server);

View File

@@ -68,8 +68,13 @@ fn codes_path(path: String) -> PathBuf {
p
}
pub fn new_token(path: String) -> Result<String, String> {
generate_new_token(path)
#[derive(Debug, PartialEq)]
pub struct SignerCommand {
pub path: String,
}
pub fn execute(cmd: SignerCommand) -> Result<String, String> {
generate_new_token(cmd.path)
.map(|code| format!("This key code will authorise your System Signer UI: {}", Colour::White.bold().paint(code)))
.map_err(|err| format!("Error generating token: {:?}", err))
}
@@ -104,7 +109,7 @@ fn do_start(conf: Configuration, deps: Dependencies) -> Result<SignerServer, Str
match start_result {
Err(signer::ServerError::IoError(err)) => match err.kind() {
io::ErrorKind::AddrInUse => Err(format!("Trusted Signer address {} is already in use, make sure that another instance of an Ethereum client is not running or change the address using the --signer-port and --signer-interface options.", addr)),
io::ErrorKind::AddrInUse => Err(format!("Trusted UI address {} is already in use, make sure that another instance of an Ethereum client is not running or change the address using the --ui-port and --ui-interface options.", addr)),
_ => Err(format!("Trusted Signer io error: {}", err)),
},
Err(e) => Err(format!("Trusted Signer Error: {:?}", e)),

View File

@@ -20,7 +20,6 @@ use std::time::Duration;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use ethcore_logger::{setup_log, Config as LogConfig};
use ethcore::snapshot::{Progress, RestorationStatus, SnapshotService as SS};
use ethcore::snapshot::io::{SnapshotReader, PackedReader, PackedWriter};
use ethcore::snapshot::service::Service as SnapshotService;
@@ -55,8 +54,6 @@ pub struct SnapshotCommand {
pub spec: SpecType,
pub pruning: Pruning,
pub pruning_history: u64,
pub logger_config: LogConfig,
pub mode: Mode,
pub tracing: Switch,
pub fat_db: Switch,
pub compaction: DatabaseCompactionProfile,
@@ -69,6 +66,8 @@ pub struct SnapshotCommand {
// helper for reading chunks from arbitrary reader and feeding them into the
// service.
fn restore_using<R: SnapshotReader>(snapshot: Arc<SnapshotService>, reader: &R, recover: bool) -> Result<(), String> {
use util::sha3::Hashable;
let manifest = reader.manifest();
info!("Restoring to block #{} (0x{:?})", manifest.block_number, manifest.block_hash);
@@ -96,6 +95,12 @@ fn restore_using<R: SnapshotReader>(snapshot: Arc<SnapshotService>, reader: &R,
let chunk = try!(reader.chunk(state_hash)
.map_err(|e| format!("Encountered error while reading chunk {:?}: {}", state_hash, e)));
let hash = chunk.sha3();
if hash != state_hash {
return Err(format!("Mismatched chunk hash. Expected {:?}, got {:?}", state_hash, hash));
}
snapshot.feed_state_chunk(state_hash, &chunk);
}
@@ -107,6 +112,11 @@ fn restore_using<R: SnapshotReader>(snapshot: Arc<SnapshotService>, reader: &R,
let chunk = try!(reader.chunk(block_hash)
.map_err(|e| format!("Encountered error while reading chunk {:?}: {}", block_hash, e)));
let hash = chunk.sha3();
if hash != block_hash {
return Err(format!("Mismatched chunk hash. Expected {:?}, got {:?}", block_hash, hash));
}
snapshot.feed_block_chunk(block_hash, &chunk);
}
@@ -141,9 +151,6 @@ impl SnapshotCommand {
// load user defaults
let user_defaults = try!(UserDefaults::load(&user_defaults_path));
// Setup logging
let _logger = setup_log(&self.logger_config);
fdlimit::raise_fd_limit();
// select pruning algorithm
@@ -163,7 +170,7 @@ impl SnapshotCommand {
try!(execute_upgrades(&db_dirs, algorithm, self.compaction.compaction_profile(db_dirs.fork_path().as_path())));
// prepare client config
let client_config = to_client_config(&self.cache_config, self.mode, tracing, fat_db, self.compaction, self.wal, VMType::default(), "".into(), algorithm, self.pruning_history, true);
let client_config = to_client_config(&self.cache_config, Mode::Active, tracing, fat_db, self.compaction, self.wal, VMType::default(), "".into(), algorithm, self.pruning_history, true);
let service = try!(ClientService::start(
client_config,

View File

@@ -18,6 +18,7 @@ use std::fs::File;
use std::io::Write;
use std::path::Path;
use std::collections::BTreeMap;
use std::time::Duration;
use serde::{Serialize, Serializer, Error, Deserialize, Deserializer};
use serde::de::{Visitor, MapVisitor};
use serde::de::impls::BTreeMapVisitor;
@@ -25,12 +26,14 @@ use serde_json::Value;
use serde_json::de::from_reader;
use serde_json::ser::to_string;
use util::journaldb::Algorithm;
use ethcore::client::Mode;
pub struct UserDefaults {
pub is_first_launch: bool,
pub pruning: Algorithm,
pub tracing: bool,
pub fat_db: bool,
pub mode: Mode,
}
impl Serialize for UserDefaults {
@@ -40,6 +43,21 @@ impl Serialize for UserDefaults {
map.insert("pruning".into(), Value::String(self.pruning.as_str().into()));
map.insert("tracing".into(), Value::Bool(self.tracing));
map.insert("fat_db".into(), Value::Bool(self.fat_db));
let mode_str = match self.mode {
Mode::Off => "offline",
Mode::Dark(timeout) => {
map.insert("mode.timeout".into(), Value::U64(timeout.as_secs()));
"dark"
},
Mode::Passive(timeout, alarm) => {
map.insert("mode.timeout".into(), Value::U64(timeout.as_secs()));
map.insert("mode.alarm".into(), Value::U64(alarm.as_secs()));
"passive"
},
Mode::Active => "active",
};
map.insert("mode".into(), Value::String(mode_str.into()));
map.serialize(serializer)
}
}
@@ -67,11 +85,28 @@ impl Visitor for UserDefaultsVisitor {
let fat_db: Value = map.remove("fat_db".into()).unwrap_or_else(|| Value::Bool(false));
let fat_db = try!(fat_db.as_bool().ok_or_else(|| Error::custom("invalid fat_db value")));
let mode: Value = map.remove("mode".into()).unwrap_or_else(|| Value::String("active".to_owned()));
let mode = match try!(mode.as_str().ok_or_else(|| Error::custom("invalid mode value"))) {
"offline" => Mode::Off,
"dark" => {
let timeout = try!(map.remove("mode.timeout".into()).and_then(|v| v.as_u64()).ok_or_else(|| Error::custom("invalid/missing mode.timeout value")));
Mode::Dark(Duration::from_secs(timeout))
},
"passive" => {
let timeout = try!(map.remove("mode.timeout".into()).and_then(|v| v.as_u64()).ok_or_else(|| Error::custom("invalid/missing mode.timeout value")));
let alarm = try!(map.remove("mode.alarm".into()).and_then(|v| v.as_u64()).ok_or_else(|| Error::custom("invalid/missing mode.alarm value")));
Mode::Passive(Duration::from_secs(timeout), Duration::from_secs(alarm))
},
"active" => Mode::Active,
_ => { return Err(Error::custom("invalid mode value")); },
};
let user_defaults = UserDefaults {
is_first_launch: false,
pruning: pruning,
tracing: tracing,
fat_db: fat_db,
mode: mode,
};
Ok(user_defaults)
@@ -85,6 +120,7 @@ impl Default for UserDefaults {
pruning: Algorithm::default(),
tracing: false,
fat_db: false,
mode: Mode::Active,
}
}
}
@@ -97,7 +133,7 @@ impl UserDefaults {
}
}
pub fn save<P>(self, path: P) -> Result<(), String> where P: AsRef<Path> {
pub fn save<P>(&self, path: P) -> Result<(), String> where P: AsRef<Path> {
let mut file: File = try!(File::create(path).map_err(|_| "Cannot create user defaults file".to_owned()));
file.write_all(to_string(&self).unwrap().as_bytes()).map_err(|_| "Failed to save user defaults".to_owned())
}