From 9836c7996239602d2beead6f2d2c035e439bb32a Mon Sep 17 00:00:00 2001 From: arkpar Date: Wed, 11 May 2016 00:08:35 +0200 Subject: [PATCH 01/12] Fixed connecting to local nodes on startup --- util/src/network/host.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/util/src/network/host.rs b/util/src/network/host.rs index 1b4d3c67f..971f3a424 100644 --- a/util/src/network/host.rs +++ b/util/src/network/host.rs @@ -466,8 +466,8 @@ impl Host where Message: Send + Sync + Clone { io.register_stream(DISCOVERY).expect("Error registering UDP listener"); io.register_timer(DISCOVERY_REFRESH, 7200).expect("Error registering discovery timer"); io.register_timer(DISCOVERY_ROUND, 300).expect("Error registering discovery timer"); - io.register_timer(NODE_TABLE, 300_000).expect("Error registering node table timer"); } + try!(io.register_timer(NODE_TABLE, 300_000)); try!(io.register_stream(TCP_ACCEPT)); Ok(()) } @@ -509,6 +509,9 @@ impl Host where Message: Send + Sync + Clone { } fn connect_peers(&self, io: &IoContext>) { + if self.info.read().unwrap().deref().capabilities.is_empty() { + return; + } let ideal_peers = { self.info.read().unwrap().deref().config.ideal_peers }; let pin = { self.info.read().unwrap().deref().config.pin }; let session_count = self.session_count(); From a22f0a0d032f23928c65accec82f83653529cfed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 11 May 2016 18:10:42 +0200 Subject: [PATCH 02/12] Updating dapp-wallet --- Cargo.lock | 6 +++--- webapp/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6fb5ccd53..7b3fbd44a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -359,7 +359,7 @@ dependencies = [ "jsonrpc-http-server 5.1.0 (git+https://github.com/ethcore/jsonrpc-http-server.git)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-status 0.3.7 (git+https://github.com/ethcore/parity-status.git)", - "parity-wallet 0.1.1 (git+https://github.com/ethcore/parity-wallet.git)", + "parity-wallet 0.2.0 (git+https://github.com/ethcore/parity-wallet.git)", "parity-webapp 0.1.0 (git+https://github.com/ethcore/parity-webapp.git)", "url 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -830,8 +830,8 @@ dependencies = [ [[package]] name = "parity-wallet" -version = "0.1.1" -source = "git+https://github.com/ethcore/parity-wallet.git#125b2c05118890eac7b845f832f39b069d9b4be8" +version = "0.2.0" +source = "git+https://github.com/ethcore/parity-wallet.git#18a602fd25f3e9bcdbc5528bf61ba627665d962c" dependencies = [ "parity-webapp 0.1.0 (git+https://github.com/ethcore/parity-webapp.git)", ] diff --git a/webapp/Cargo.toml b/webapp/Cargo.toml index fd94336bb..51f54f02d 100644 --- a/webapp/Cargo.toml +++ b/webapp/Cargo.toml @@ -18,7 +18,7 @@ ethcore-util = { path = "../util" } parity-webapp = { git = "https://github.com/ethcore/parity-webapp.git" } # List of apps parity-status = { git = "https://github.com/ethcore/parity-status.git", version = "0.3.7" } -parity-wallet = { git = "https://github.com/ethcore/parity-wallet.git", version = "0.1.1", optional = true } +parity-wallet = { git = "https://github.com/ethcore/parity-wallet.git", version = "0.2.0", optional = true } clippy = { version = "0.0.64", optional = true} [features] From 4a8fe6c99d2bfd3b558f1e96b978aa19c9c02299 Mon Sep 17 00:00:00 2001 From: Brian Muhia Date: Sun, 27 Mar 2016 21:38:59 +0300 Subject: [PATCH 03/12] Update error message --- devtools/src/random_path.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devtools/src/random_path.rs b/devtools/src/random_path.rs index b037867fa..990d375e3 100644 --- a/devtools/src/random_path.rs +++ b/devtools/src/random_path.rs @@ -59,7 +59,7 @@ impl RandomTempPath { impl Drop for RandomTempPath { fn drop(&mut self) { if let Err(e) = fs::remove_dir_all(self.as_path()) { - panic!("failed to remove temp directory, probably something failed to destroyed ({})", e); + panic!("Failed to remove temp directory. Here's what prevented this from happening: ({})", e); } } } From d5d5b0918cca6c4cc9b61f271ad3fd7295c9f72a Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Fri, 13 May 2016 13:11:50 +0300 Subject: [PATCH 04/12] mod for paths & ethereum default paths --- util/src/keys/geth_import.rs | 26 ++-------------- util/src/lib.rs | 1 + util/src/path.rs | 57 ++++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 24 deletions(-) create mode 100644 util/src/path.rs diff --git a/util/src/keys/geth_import.rs b/util/src/keys/geth_import.rs index 9886a61a8..56e73f790 100644 --- a/util/src/keys/geth_import.rs +++ b/util/src/keys/geth_import.rs @@ -20,6 +20,7 @@ use common::*; use keys::store::SecretStore; use keys::directory::KeyFileContent; use std::path::PathBuf; +use path; /// Enumerates all geth keys in the directory and returns collection of tuples `(accountId, filename)` pub fn enumerate_geth_keys(path: &Path) -> Result, ImportError> { @@ -98,30 +99,7 @@ pub fn import_geth_keys(secret_store: &mut SecretStore, geth_keyfiles_directory: /// /// Based on https://github.com/ethereum/go-ethereum/blob/e553215/common/path.go#L75 pub fn keystore_dir() -> PathBuf { - #[cfg(target_os = "macos")] - fn data_dir(mut home: PathBuf) -> PathBuf { - home.push("Library"); - home.push("Ethereum"); - home - } - - #[cfg(windows)] - fn data_dir(mut home: PathBuf) -> PathBuf { - home.push("AppData"); - home.push("Roaming"); - home.push("Ethereum"); - home - } - - #[cfg(not(any(target_os = "macos", windows)))] - fn data_dir(mut home: PathBuf) -> PathBuf { - home.push(".ethereum"); - home - } - - let mut data_dir = data_dir(::std::env::home_dir().expect("Failed to get home dir")); - data_dir.push("keystore"); - data_dir + path::ethereum::with_default("keystore") } #[cfg(test)] diff --git a/util/src/lib.rs b/util/src/lib.rs index 530f2b4c5..a97282198 100644 --- a/util/src/lib.rs +++ b/util/src/lib.rs @@ -148,6 +148,7 @@ pub mod panics; pub mod keys; pub mod table; pub mod network_settings; +pub mod path; pub use common::*; pub use misc::*; diff --git a/util/src/path.rs b/util/src/path.rs new file mode 100644 index 000000000..10aaca44a --- /dev/null +++ b/util/src/path.rs @@ -0,0 +1,57 @@ +// Copyright 2015, 2016 Ethcore (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 . + +//! Path utilities + +/// Default ethereum paths +pub mod ethereum { + use std::path::PathBuf; + + #[cfg(target_os = "macos")] + /// Default path for ethereum installation on Mac Os + pub fn default() -> PathBuf { + let mut home = ::std::env::home_dir().expect("Failed to get home dir"); + home.push("Library"); + home.push("Ethereum"); + home + } + + #[cfg(windows)] + /// Default path for ethereum installation on Windows + pub fn default() -> PathBuf { + let mut home = ::std::env::home_dir().expect("Failed to get home dir"); + home.push("AppData"); + home.push("Roaming"); + home.push("Ethereum"); + home + } + + #[cfg(not(any(target_os = "macos", windows)))] + /// Default path for ethereum installation on posix system which and not Mac OS + pub fn default() -> PathBuf { + let mut home = ::std::env::home_dir().expect("Failed to get home dir"); + home.push(".ethereum"); + home + } + + /// Get the specific folder inside default ethereum installation + pub fn with_default(s: &str) -> PathBuf { + let mut pth = default(); + pth.push(s); + pth + } +} + From 9150538ac4503db1a691fba97ba226168ad570a7 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Fri, 13 May 2016 13:53:33 +0300 Subject: [PATCH 05/12] refactoring in configuration --- parity/configuration.rs | 27 +++++++++++++++------------ util/src/path.rs | 3 +-- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/parity/configuration.rs b/parity/configuration.rs index 8d0eea9bb..90b5b3d1d 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -61,8 +61,7 @@ impl Configuration { } pub fn path(&self) -> String { - let d = self.args.flag_datadir.as_ref().unwrap_or(&self.args.flag_db_path); - d.replace("$HOME", env::home_dir().unwrap().to_str().unwrap()) + Configuration::replace_home(&self.args.flag_datadir.as_ref().unwrap_or(&self.args.flag_db_path)) } pub fn author(&self) -> Address { @@ -114,7 +113,7 @@ impl Configuration { } pub fn keys_path(&self) -> String { - self.args.flag_keys_path.replace("$HOME", env::home_dir().unwrap().to_str().unwrap()) + Configuration::replace_home(&self.args.flag_keys_path) } pub fn spec(&self) -> Spec { @@ -266,20 +265,24 @@ impl Configuration { pub fn rpc_cors(&self) -> Option { self.args.flag_jsonrpc_cors.clone().or(self.args.flag_rpccorsdomain.clone()) } - - fn geth_ipc_path() -> &'static str { - if cfg!(target_os = "macos") { - "$HOME/Library/Ethereum/geth.ipc" - } else { - "$HOME/.ethereum/geth.ipc" - } + + fn geth_ipc_path() -> String { + path::ethereum::with_default("geth.ipc").to_str().unwrap().to_owned() + } + + fn replace_home(arg: &str) -> String { + arg.replace("$HOME", env::home_dir().unwrap().to_str().unwrap()) + } + + fn ipc_path(&self) -> String { + if self.args.flag_geth { Self::geth_ipc_path() } + else { Configuration::replace_home(&self.args.flag_ipcpath.clone().unwrap_or(self.args.flag_ipc_path.clone())) } } pub fn ipc_settings(&self) -> IpcConfiguration { IpcConfiguration { enabled: !(self.args.flag_ipcdisable || self.args.flag_ipc_off), - socket_addr: if self.args.flag_geth { Self::geth_ipc_path().to_owned() } else { self.args.flag_ipcpath.clone().unwrap_or(self.args.flag_ipc_path.clone()) } - .replace("$HOME", env::home_dir().unwrap().to_str().unwrap()), + socket_addr: self.ipc_path(), apis: self.args.flag_ipcapi.clone().unwrap_or(self.args.flag_ipc_apis.clone()), } } diff --git a/util/src/path.rs b/util/src/path.rs index 10aaca44a..3a8dcaaae 100644 --- a/util/src/path.rs +++ b/util/src/path.rs @@ -40,7 +40,7 @@ pub mod ethereum { } #[cfg(not(any(target_os = "macos", windows)))] - /// Default path for ethereum installation on posix system which and not Mac OS + /// Default path for ethereum installation on posix system which is not Mac OS pub fn default() -> PathBuf { let mut home = ::std::env::home_dir().expect("Failed to get home dir"); home.push(".ethereum"); @@ -54,4 +54,3 @@ pub mod ethereum { pth } } - From 7c19930efa01c391262b320a34d711114d594957 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Fri, 13 May 2016 18:32:32 +0300 Subject: [PATCH 06/12] creating all in one place --- parity/configuration.rs | 52 +++++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/parity/configuration.rs b/parity/configuration.rs index 90b5b3d1d..ed28d0725 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -37,6 +37,11 @@ pub struct Configuration { pub args: Args } +pub struct Directories { + pub keys: String, + pub db: String, +} + impl Configuration { pub fn parse() -> Self { Configuration { @@ -60,10 +65,6 @@ impl Configuration { self.args.flag_maxpeers.unwrap_or(self.args.flag_peers) as u32 } - pub fn path(&self) -> String { - Configuration::replace_home(&self.args.flag_datadir.as_ref().unwrap_or(&self.args.flag_db_path)) - } - pub fn author(&self) -> Address { let d = self.args.flag_etherbase.as_ref().unwrap_or(&self.args.flag_author); Address::from_str(clean_0x(d)).unwrap_or_else(|_| { @@ -112,10 +113,6 @@ impl Configuration { } } - pub fn keys_path(&self) -> String { - Configuration::replace_home(&self.args.flag_keys_path) - } - pub fn spec(&self) -> Spec { match self.chain().as_str() { "frontier" | "homestead" | "mainnet" => ethereum::new_frontier(), @@ -270,15 +267,6 @@ impl Configuration { path::ethereum::with_default("geth.ipc").to_str().unwrap().to_owned() } - fn replace_home(arg: &str) -> String { - arg.replace("$HOME", env::home_dir().unwrap().to_str().unwrap()) - } - - fn ipc_path(&self) -> String { - if self.args.flag_geth { Self::geth_ipc_path() } - else { Configuration::replace_home(&self.args.flag_ipcpath.clone().unwrap_or(self.args.flag_ipc_path.clone())) } - } - pub fn ipc_settings(&self) -> IpcConfiguration { IpcConfiguration { enabled: !(self.args.flag_ipcdisable || self.args.flag_ipc_off), @@ -299,6 +287,36 @@ impl Configuration { rpc_port: self.args.flag_rpcport.unwrap_or(self.args.flag_jsonrpc_port), } } + + pub fn directories(&self) -> Directories { + let db_path = Configuration::replace_home( + &self.args.flag_datadir.as_ref().unwrap_or(&self.args.flag_db_path)); + std::fs::create_dir_all(db_path).unwrap_or_else(|e| die_with_io_error(e)); + + let keys_path = Configuration::replace_home(&self.args.flag_keys_path); + + Directories { + keys: keys_path, + db: db_path, + } + } + + pub fn keys_path(&self) -> String { + self.directories().keys + } + + pub fn path(&self) -> String { + self.directories().db + } + + fn replace_home(arg: &str) -> String { + arg.replace("$HOME", env::home_dir().unwrap().to_str().unwrap()) + } + + fn ipc_path(&self) -> String { + if self.args.flag_geth { Self::geth_ipc_path() } + else { Configuration::replace_home(&self.args.flag_ipcpath.clone().unwrap_or(self.args.flag_ipc_path.clone())) } + } } #[cfg(test)] From 96496d634953d8de4838608bc24b4ba04960eb34 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Fri, 13 May 2016 18:36:18 +0300 Subject: [PATCH 07/12] by ref --- parity/configuration.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/parity/configuration.rs b/parity/configuration.rs index ed28d0725..920cb7eed 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -291,9 +291,10 @@ impl Configuration { pub fn directories(&self) -> Directories { let db_path = Configuration::replace_home( &self.args.flag_datadir.as_ref().unwrap_or(&self.args.flag_db_path)); - std::fs::create_dir_all(db_path).unwrap_or_else(|e| die_with_io_error(e)); + ::std::fs::create_dir_all(&db_path).unwrap_or_else(|e| die_with_io_error("main", e)); let keys_path = Configuration::replace_home(&self.args.flag_keys_path); + ::std::fs::create_dir_all(&db_path).unwrap_or_else(|e| die_with_io_error("main", e)); Directories { keys: keys_path, From 9b914446389b2f5755625720eeb618a7e6bbcacd Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Sat, 14 May 2016 13:29:26 +0200 Subject: [PATCH 08/12] comma delimeting multiple cors headers (#1078) --- Cargo.lock | 12 +++++++++++- parity/configuration.rs | 9 +++++---- parity/rpc.rs | 6 +++--- rpc/Cargo.toml | 2 +- rpc/src/lib.rs | 8 +++++--- 5 files changed, 25 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7b3fbd44a..c409cf58a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -301,7 +301,7 @@ dependencies = [ "ethsync 1.2.0", "json-ipc-server 0.1.0 (git+https://github.com/ethcore/json-ipc-server.git)", "jsonrpc-core 2.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-http-server 5.1.0 (git+https://github.com/ethcore/jsonrpc-http-server.git)", + "jsonrpc-http-server 5.1.0 (git+https://github.com/ethcore/jsonrpc-http-server.git?branch=multiple_cors_domains)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -577,6 +577,16 @@ dependencies = [ "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "jsonrpc-http-server" +version = "5.1.0" +source = "git+https://github.com/ethcore/jsonrpc-http-server.git?branch=multiple_cors_domains#9c026feeb6573c82c99c8005c5d8244de68a2e30" +dependencies = [ + "hyper 0.9.3 (git+https://github.com/ethcore/hyper)", + "jsonrpc-core 2.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "kernel32-sys" version = "0.2.2" diff --git a/parity/configuration.rs b/parity/configuration.rs index 8d0eea9bb..c7c3480f9 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -263,10 +263,11 @@ impl Configuration { self.args.flag_rpcapi.clone().unwrap_or(self.args.flag_jsonrpc_apis.clone()) } - pub fn rpc_cors(&self) -> Option { - self.args.flag_jsonrpc_cors.clone().or(self.args.flag_rpccorsdomain.clone()) + pub fn rpc_cors(&self) -> Vec { + let cors = self.args.flag_jsonrpc_cors.clone().or(self.args.flag_rpccorsdomain.clone()); + cors.map_or_else(Vec::new, |c| c.split(',').map(|s| s.to_owned()).collect()) } - + fn geth_ipc_path() -> &'static str { if cfg!(target_os = "macos") { "$HOME/Library/Ethereum/geth.ipc" @@ -338,7 +339,7 @@ mod tests { assert_eq!(net.rpc_enabled, true); assert_eq!(net.rpc_interface, "all".to_owned()); assert_eq!(net.rpc_port, 8000); - assert_eq!(conf.rpc_cors(), Some("*".to_owned())); + assert_eq!(conf.rpc_cors(), vec!["*".to_owned()]); assert_eq!(conf.rpc_apis(), "web3,eth".to_owned()); } diff --git a/parity/rpc.rs b/parity/rpc.rs index a48af6401..e1782e9b6 100644 --- a/parity/rpc.rs +++ b/parity/rpc.rs @@ -41,7 +41,7 @@ pub struct HttpConfiguration { pub interface: String, pub port: u16, pub apis: String, - pub cors: Option, + pub cors: Vec, } pub struct IpcConfiguration { @@ -139,11 +139,11 @@ pub fn setup_http_rpc_server( pub fn setup_http_rpc_server( dependencies: &Arc, url: &SocketAddr, - cors_domain: Option, + cors_domains: Vec, apis: Vec<&str>, ) -> RpcServer { let server = setup_rpc_server(apis, dependencies); - let start_result = server.start_http(url, cors_domain); + let start_result = server.start_http(url, cors_domains); let deps = dependencies.clone(); match start_result { Err(RpcServerError::IoError(err)) => die_with_io_error("RPC", err), diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index 326634ab2..c4de059bf 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -13,7 +13,7 @@ log = "0.3" serde = "0.7.0" serde_json = "0.7.0" jsonrpc-core = "2.0" -jsonrpc-http-server = { git = "https://github.com/ethcore/jsonrpc-http-server.git" } +jsonrpc-http-server = { git = "https://github.com/ethcore/jsonrpc-http-server.git", branch = "multiple_cors_domains" } ethcore-util = { path = "../util" } ethcore = { path = "../ethcore" } ethash = { path = "../ethash" } diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index d4998fdc3..7d9818615 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -59,9 +59,11 @@ impl RpcServer { } /// Start http server asynchronously and returns result with `Server` handle on success or an error. - pub fn start_http(&self, addr: &SocketAddr, cors_domain: Option) -> Result { - let cors_domain = cors_domain.to_owned(); - Server::start(addr, self.handler.clone(), cors_domain.map(jsonrpc_http_server::AccessControlAllowOrigin::Value)) + pub fn start_http(&self, addr: &SocketAddr, cors_domains: Vec) -> Result { + let cors_domains = cors_domains.into_iter() + .map(jsonrpc_http_server::AccessControlAllowOrigin::Value) + .collect(); + Server::start(addr, self.handler.clone(), cors_domains) } /// Start ipc server asynchronously and returns result with `Server` handle on success or an error. From 2b78e511c9e08af9647d91cf6e8718900c753a55 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Sat, 14 May 2016 14:30:25 +0300 Subject: [PATCH 09/12] Configurable keys security (#1080) * adding options & cli flags * adding it to the key deriving * removed duplicated option --- parity/cli.rs | 4 ++++ parity/configuration.rs | 6 +++++- parity/main.rs | 2 +- util/src/keys/store.rs | 25 +++++++++++++++++++------ 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/parity/cli.rs b/parity/cli.rs index 84c941d33..009f03b89 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -42,6 +42,9 @@ Account Options: ACCOUNTS is a comma-delimited list of addresses. --password FILE Provide a file containing a password for unlocking an account. + --keys-iterations NUM Specify the number of iterations to use when deriving key + from the password (bigger is more secure) + [default: 10240]. Networking Options: --port PORT Override the port on which the node should listen @@ -182,6 +185,7 @@ pub struct Args { pub flag_password: Vec, pub flag_cache: Option, pub flag_keys_path: String, + pub flag_keys_iterations: u32, pub flag_bootnodes: Option, pub flag_network_id: Option, pub flag_pruning: String, diff --git a/parity/configuration.rs b/parity/configuration.rs index c7c3480f9..96885f83b 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -117,6 +117,10 @@ impl Configuration { self.args.flag_keys_path.replace("$HOME", env::home_dir().unwrap().to_str().unwrap()) } + pub fn keys_iterations(&self) -> u32 { + self.args.flag_keys_iterations + } + pub fn spec(&self) -> Spec { match self.chain().as_str() { "frontier" | "homestead" | "mainnet" => ethereum::new_frontier(), @@ -245,7 +249,7 @@ impl Configuration { .collect::>() .into_iter() }).collect::>(); - let account_service = AccountService::new_in(Path::new(&self.keys_path())); + let account_service = AccountService::with_security(Path::new(&self.keys_path()), self.keys_iterations()); if let Some(ref unlocks) = self.args.flag_unlock { for d in unlocks.split(',') { let a = Address::from_str(clean_0x(&d)).unwrap_or_else(|_| { diff --git a/parity/main.rs b/parity/main.rs index ded07505c..dd70d39cc 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -219,7 +219,7 @@ fn flush_stdout() { fn execute_account_cli(conf: Configuration) { use util::keys::store::SecretStore; use rpassword::read_password; - let mut secret_store = SecretStore::new_in(Path::new(&conf.keys_path())); + let mut secret_store = SecretStore::with_security(Path::new(&conf.keys_path()), conf.keys_iterations()); if conf.args.cmd_new { println!("Please note that password is NOT RECOVERABLE."); print!("Type password: "); diff --git a/util/src/keys/store.rs b/util/src/keys/store.rs index a879a4cd2..bf5edf3c9 100644 --- a/util/src/keys/store.rs +++ b/util/src/keys/store.rs @@ -73,6 +73,7 @@ pub enum SigningError { pub struct SecretStore { directory: KeyDirectory, unlocks: RwLock>, + key_iterations: u32, } struct AccountUnlock { @@ -128,10 +129,15 @@ impl AccountProvider for AccountService { impl AccountService { /// New account service with the keys store in specific location pub fn new_in(path: &Path) -> Self { - let secret_store = RwLock::new(SecretStore::new_in(path)); + AccountService::with_security(path, KEY_ITERATIONS) + } + + /// New account service with the keys store in specific location and configured security parameters + pub fn with_security(path: &Path, key_iterations: u32) -> Self { + let secret_store = RwLock::new(SecretStore::with_security(path, key_iterations)); secret_store.write().unwrap().try_import_existing(); AccountService { - secret_store: secret_store + secret_store: secret_store, } } @@ -157,10 +163,16 @@ impl AccountService { impl SecretStore { /// new instance of Secret Store in specific directory pub fn new_in(path: &Path) -> Self { + SecretStore::with_security(path, KEY_ITERATIONS) + } + + /// new instance of Secret Store in specific directory and configured security parameters + pub fn with_security(path: &Path, key_iterations: u32) -> Self { ::std::fs::create_dir_all(&path).expect("Cannot access requested key directory - critical"); SecretStore { directory: KeyDirectory::new(path), unlocks: RwLock::new(HashMap::new()), + key_iterations: key_iterations, } } @@ -206,6 +218,7 @@ impl SecretStore { SecretStore { directory: KeyDirectory::new(path.as_path()), unlocks: RwLock::new(HashMap::new()), + key_iterations: KEY_ITERATIONS, } } @@ -289,8 +302,8 @@ fn derive_key_iterations(password: &str, salt: &H256, c: u32) -> (Bytes, Bytes) (derived_right_bits.to_vec(), derived_left_bits.to_vec()) } -fn derive_key(password: &str, salt: &H256) -> (Bytes, Bytes) { - derive_key_iterations(password, salt, KEY_ITERATIONS) +fn derive_key(password: &str, salt: &H256, iterations: u32) -> (Bytes, Bytes) { + derive_key_iterations(password, salt, iterations) } fn derive_key_scrypt(password: &str, salt: &H256, n: u32, p: u32, r: u32) -> (Bytes, Bytes) { @@ -346,7 +359,7 @@ impl EncryptedHashMap for SecretStore { // two parts of derived key // DK = [ DK[0..15] DK[16..31] ] = [derived_left_bits, derived_right_bits] - let (derived_left_bits, derived_right_bits) = derive_key(password, &salt); + let (derived_left_bits, derived_right_bits) = derive_key(password, &salt, self.key_iterations); let mut cipher_text = vec![0u8; value.as_slice().len()]; // aes-128-ctr with initial vector of iv @@ -361,7 +374,7 @@ impl EncryptedHashMap for SecretStore { iv, salt, mac, - KEY_ITERATIONS, + self.key_iterations, KEY_LENGTH)); key_file.id = key; if let Err(io_error) = self.directory.save(key_file) { From 354ac7d6e596ae5c5752d3863884a43ecb625a84 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Sat, 14 May 2016 15:28:44 +0300 Subject: [PATCH 10/12] Limiting result of the execution to execution-specific errors (#1071) * execution error/result limiting * missing trailing comma * fix executive tests * adding original error as string to the generic transaction error * 'mallformed'-s all around --- ethcore/src/client/client.rs | 7 +++++-- ethcore/src/client/mod.rs | 4 ++-- ethcore/src/client/test_client.rs | 4 ++-- ethcore/src/error.rs | 4 +++- ethcore/src/executive.rs | 19 +++++++++++-------- miner/src/lib.rs | 4 ++-- miner/src/miner.rs | 7 +++++-- rpc/src/v1/tests/helpers/miner_service.rs | 4 ++-- sync/src/chain.rs | 4 ++-- util/src/keys/directory.rs | 2 +- 10 files changed, 35 insertions(+), 24 deletions(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 23b81b34e..e385f39a8 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -424,7 +424,7 @@ impl Client where V: Verifier { } impl BlockChainClient for Client where V: Verifier { - fn call(&self, t: &SignedTransaction) -> Result { + fn call(&self, t: &SignedTransaction) -> Result { let header = self.block_header(BlockId::Latest).unwrap(); let view = HeaderView::new(&header); let last_hashes = self.build_last_hashes(view.hash()); @@ -439,7 +439,10 @@ impl BlockChainClient for Client where V: Verifier { }; // that's just a copy of the state. let mut state = self.state(); - let sender = try!(t.sender()); + let sender = try!(t.sender().map_err(|e| { + let message = format!("Transaction malformed: {:?}", e); + ExecutionError::TransactionMalformed(message) + })); let balance = state.balance(&sender); // give the sender max balance state.sub_balance(&sender, &balance); diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index 90dd78015..9dddeceb7 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -42,7 +42,7 @@ use header::{BlockNumber, Header}; use transaction::{LocalizedTransaction, SignedTransaction}; use log_entry::LocalizedLogEntry; use filter::Filter; -use error::{ImportResult, Error}; +use error::{ImportResult, ExecutionError}; use receipt::LocalizedReceipt; use engine::{Engine}; use trace::LocalizedTrace; @@ -133,7 +133,7 @@ pub trait BlockChainClient : Sync + Send { fn try_seal(&self, block: LockedBlock, seal: Vec) -> Result; /// Makes a non-persistent transaction call. - fn call(&self, t: &SignedTransaction) -> Result; + fn call(&self, t: &SignedTransaction) -> Result; /// Attempt to seal the block internally. See `Engine`. fn generate_seal(&self, block: &ExecutedBlock, accounts: Option<&AccountProvider>) -> Option> { self.engine().generate_seal(block, accounts) } diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index c3df57b76..4ec993fe5 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -31,7 +31,7 @@ use error::{ImportResult}; use block_queue::BlockQueueInfo; use block::{SealedBlock, ClosedBlock, LockedBlock}; use executive::Executed; -use error::Error; +use error::{ExecutionError}; use engine::Engine; use trace::LocalizedTrace; @@ -221,7 +221,7 @@ impl TestBlockChainClient { } impl BlockChainClient for TestBlockChainClient { - fn call(&self, _t: &SignedTransaction) -> Result { + fn call(&self, _t: &SignedTransaction) -> Result { Ok(self.execution_result.read().unwrap().clone().unwrap()) } diff --git a/ethcore/src/error.rs b/ethcore/src/error.rs index 922d72700..2e007703b 100644 --- a/ethcore/src/error.rs +++ b/ethcore/src/error.rs @@ -59,7 +59,9 @@ pub enum ExecutionError { got: U512 }, /// Returned when internal evm error occurs. - Internal + Internal, + /// Returned when generic transaction occurs + TransactionMalformed(String), } #[derive(Debug, PartialEq)] diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index 4247114ef..179195078 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -119,7 +119,7 @@ impl<'a> Executive<'a> { } /// This function should be used to execute transaction. - pub fn transact(&'a mut self, t: &SignedTransaction, options: TransactOptions) -> Result { + pub fn transact(&'a mut self, t: &SignedTransaction, options: TransactOptions) -> Result { let check = options.check_nonce; match options.tracing { true => self.transact_with_tracer(t, check, ExecutiveTracer::default()), @@ -128,8 +128,11 @@ impl<'a> Executive<'a> { } /// Execute transaction/call with tracing enabled - pub fn transact_with_tracer(&'a mut self, t: &SignedTransaction, check_nonce: bool, mut tracer: T) -> Result where T: Tracer { - let sender = try!(t.sender()); + pub fn transact_with_tracer(&'a mut self, t: &SignedTransaction, check_nonce: bool, mut tracer: T) -> Result where T: Tracer { + let sender = try!(t.sender().map_err(|e| { + let message = format!("Transaction malformed: {:?}", e); + ExecutionError::TransactionMalformed(message) + })); let nonce = self.state.nonce(&sender); let schedule = self.engine.schedule(self.info); @@ -983,8 +986,8 @@ mod tests { }; match res { - Err(Error::Util(UtilError::Crypto(CryptoError::InvalidSignature))) => (), - _ => assert!(false, "Expected invalid signature error.") + Err(ExecutionError::TransactionMalformed(_)) => (), + _ => assert!(false, "Expected an invalid transaction error.") } } @@ -1015,7 +1018,7 @@ mod tests { }; match res { - Err(Error::Execution(ExecutionError::InvalidNonce { expected, got })) + Err(ExecutionError::InvalidNonce { expected, got }) if expected == U256::zero() && got == U256::one() => (), _ => assert!(false, "Expected invalid nonce error.") } @@ -1049,7 +1052,7 @@ mod tests { }; match res { - Err(Error::Execution(ExecutionError::BlockGasLimitReached { gas_limit, gas_used, gas })) + Err(ExecutionError::BlockGasLimitReached { gas_limit, gas_used, gas }) if gas_limit == U256::from(100_000) && gas_used == U256::from(20_000) && gas == U256::from(80_001) => (), _ => assert!(false, "Expected block gas limit error.") } @@ -1083,7 +1086,7 @@ mod tests { }; match res { - Err(Error::Execution(ExecutionError::NotEnoughCash { required , got })) + Err(ExecutionError::NotEnoughCash { required , got }) if required == U512::from(100_018) && got == U512::from(100_017) => (), _ => assert!(false, "Expected not enough cash error. {:?}", res) } diff --git a/miner/src/lib.rs b/miner/src/lib.rs index bd2904fc2..f92e0de52 100644 --- a/miner/src/lib.rs +++ b/miner/src/lib.rs @@ -63,7 +63,7 @@ pub use external::{ExternalMiner, ExternalMinerService}; use util::{H256, U256, Address, Bytes}; use ethcore::client::{BlockChainClient, Executed}; use ethcore::block::{ClosedBlock}; -use ethcore::error::{Error}; +use ethcore::error::{Error, ExecutionError}; use ethcore::transaction::SignedTransaction; /// Miner client API @@ -150,7 +150,7 @@ pub trait MinerService : Send + Sync { fn balance(&self, chain: &BlockChainClient, address: &Address) -> U256; /// Call into contract code using pending state. - fn call(&self, chain: &BlockChainClient, t: &SignedTransaction) -> Result; + fn call(&self, chain: &BlockChainClient, t: &SignedTransaction) -> Result; /// Get storage value in pending state. fn storage_at(&self, chain: &BlockChainClient, address: &Address, position: &H256) -> H256; diff --git a/miner/src/miner.rs b/miner/src/miner.rs index 78ff824f6..33d21613f 100644 --- a/miner/src/miner.rs +++ b/miner/src/miner.rs @@ -240,7 +240,7 @@ impl MinerService for Miner { } } - fn call(&self, chain: &BlockChainClient, t: &SignedTransaction) -> Result { + fn call(&self, chain: &BlockChainClient, t: &SignedTransaction) -> Result { let sealing_work = self.sealing_work.lock().unwrap(); match sealing_work.peek_last_ref() { Some(work) => { @@ -258,7 +258,10 @@ impl MinerService for Miner { }; // that's just a copy of the state. let mut state = block.state().clone(); - let sender = try!(t.sender()); + let sender = try!(t.sender().map_err(|e| { + let message = format!("Transaction malformed: {:?}", e); + ExecutionError::TransactionMalformed(message) + })); let balance = state.balance(&sender); // give the sender max balance state.sub_balance(&sender, &balance); diff --git a/rpc/src/v1/tests/helpers/miner_service.rs b/rpc/src/v1/tests/helpers/miner_service.rs index cd4157fa9..1fbe15ca4 100644 --- a/rpc/src/v1/tests/helpers/miner_service.rs +++ b/rpc/src/v1/tests/helpers/miner_service.rs @@ -18,7 +18,7 @@ use util::{Address, H256, Bytes, U256, FixedHash, Uint}; use util::standard::*; -use ethcore::error::Error; +use ethcore::error::{Error, ExecutionError}; use ethcore::client::{BlockChainClient, Executed}; use ethcore::block::{ClosedBlock, IsBlock}; use ethcore::transaction::SignedTransaction; @@ -179,7 +179,7 @@ impl MinerService for TestMinerService { self.latest_closed_block.lock().unwrap().as_ref().map_or_else(U256::zero, |b| b.block().fields().state.balance(address).clone()) } - fn call(&self, _chain: &BlockChainClient, _t: &SignedTransaction) -> Result { + fn call(&self, _chain: &BlockChainClient, _t: &SignedTransaction) -> Result { unimplemented!(); } diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 14809fdc4..bd94fb9be 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -1193,7 +1193,7 @@ impl ChainSync { let mut rlp_stream = RlpStream::new_list(route.blocks.len()); for block_hash in route.blocks { let mut hash_rlp = RlpStream::new_list(2); - let difficulty = chain.block_total_difficulty(BlockId::Hash(block_hash.clone())).expect("Mallformed block without a difficulty on the chain!"); + let difficulty = chain.block_total_difficulty(BlockId::Hash(block_hash.clone())).expect("Malformed block without a difficulty on the chain!"); hash_rlp.append(&block_hash); hash_rlp.append(&difficulty); rlp_stream.append_raw(&hash_rlp.out(), 1); @@ -1570,7 +1570,7 @@ mod tests { } #[test] - fn handles_peer_new_block_mallformed() { + fn handles_peer_new_block_malformed() { let mut client = TestBlockChainClient::new(); client.add_blocks(10, EachBlockWith::Uncle); diff --git a/util/src/keys/directory.rs b/util/src/keys/directory.rs index d9268a95f..3f4100163 100644 --- a/util/src/keys/directory.rs +++ b/util/src/keys/directory.rs @@ -381,7 +381,7 @@ impl KeyFileContent { } } - /// Loads key from valid json, returns error and records warning if key is mallformed + /// Loads key from valid json, returns error and records warning if key is malformed pub fn load(json: &Json) -> Result { match Self::from_json(json) { Ok(key_file) => Ok(key_file), From 33248528b9ed1f1f8d168b98f3b2d1f13d86584f Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 14 May 2016 14:53:46 +0100 Subject: [PATCH 11/12] Provide fallback for usd-per-eth option when offline. Fixes #1073. --- parity/cli.rs | 4 +++- parity/configuration.rs | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/parity/cli.rs b/parity/cli.rs index 009f03b89..90d7167dc 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -102,7 +102,9 @@ Sealing/Mining Options: [default: 0.005]. The minimum gas price is set accordingly. --usd-per-eth SOURCE USD value of a single ETH. SOURCE may be either an - amount in USD or a web service [default: etherscan]. + amount in USD, a web service or 'auto' to use each + web service in turn and fallback on the last known + good value [default: auto]. --gas-floor-target GAS Amount of gas per block to target when sealing a new block [default: 4712388]. --author ADDRESS Specify the block author (aka "coinbase") address diff --git a/parity/configuration.rs b/parity/configuration.rs index 96885f83b..ede71029c 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -91,11 +91,18 @@ impl Configuration { die!("{}: Invalid basic transaction price given in USD. Must be a decimal number.", self.args.flag_usd_per_tx) }); let usd_per_eth = match self.args.flag_usd_per_eth.as_str() { + "auto" => PriceInfo::get().map_or_else(|| { + let last_known_good = 9.69696; + // TODO: use #1083 to read last known good value. + last_known_good + }, |x| x.ethusd), "etherscan" => PriceInfo::get().map_or_else(|| { die!("Unable to retrieve USD value of ETH from etherscan. Rerun with a different value for --usd-per-eth.") }, |x| x.ethusd), x => FromStr::from_str(x).unwrap_or_else(|_| die!("{}: Invalid ether price given in USD. Must be a decimal number.", x)) }; + // TODO: use #1083 to write last known good value as use_per_eth. + let wei_per_usd: f32 = 1.0e18 / usd_per_eth; let gas_per_tx: f32 = 21000.0; let wei_per_gas: f32 = wei_per_usd * usd_per_tx / gas_per_tx; From 3ea26fcb0a5f699b7695c8c692b5475954f4d98c Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Sat, 14 May 2016 20:43:29 +0300 Subject: [PATCH 12/12] merged out function return --- parity/configuration.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/parity/configuration.rs b/parity/configuration.rs index 2f2a1cc74..67fc30f32 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -268,6 +268,10 @@ impl Configuration { path::ethereum::with_default("geth.ipc").to_str().unwrap().to_owned() } + pub fn keys_iterations(&self) -> u32 { + self.args.flag_keys_iterations + } + pub fn ipc_settings(&self) -> IpcConfiguration { IpcConfiguration { enabled: !(self.args.flag_ipcdisable || self.args.flag_ipc_off),