diff --git a/accounts/ethkey/cli/src/main.rs b/accounts/ethkey/cli/src/main.rs index a2f26f34a0d..7fee35e0d7b 100644 --- a/accounts/ethkey/cli/src/main.rs +++ b/accounts/ethkey/cli/src/main.rs @@ -14,6 +14,53 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . +#![warn( + clippy::all, + clippy::pedantic, + clippy::nursery, +)] +#![allow( + clippy::blacklisted_name, + clippy::cast_lossless, + clippy::cast_possible_truncation, + clippy::cast_possible_wrap, + clippy::cast_precision_loss, + clippy::cast_ptr_alignment, + clippy::cast_sign_loss, + clippy::cognitive_complexity, + clippy::default_trait_access, + clippy::enum_glob_use, + clippy::eval_order_dependence, + clippy::fallible_impl_from, + clippy::float_cmp, + clippy::identity_op, + clippy::if_not_else, + clippy::indexing_slicing, + clippy::inline_always, + clippy::items_after_statements, + clippy::large_enum_variant, + clippy::match_same_arms, + clippy::missing_errors_doc, + clippy::missing_safety_doc, + clippy::module_inception, + clippy::module_name_repetitions, + clippy::must_use_candidate, + clippy::needless_pass_by_value, + clippy::needless_update, + clippy::non_ascii_literal, + clippy::option_option, + clippy::pub_enum_variant_names, + clippy::same_functions_in_if_condition, + clippy::shadow_unrelated, + clippy::similar_names, + clippy::single_component_path_imports, + clippy::too_many_arguments, + clippy::too_many_lines, + clippy::type_complexity, + clippy::unused_self, + clippy::used_underscore_binding, +)] + extern crate docopt; extern crate env_logger; extern crate ethkey; @@ -35,7 +82,7 @@ use ethkey::{Brain, BrainPrefix, Prefix, brain_recover}; use parity_crypto::publickey::{KeyPair, Random, Error as EthkeyError, Generator, sign, verify_public, verify_address}; use rustc_hex::{FromHex, FromHexError}; -const USAGE: &'static str = r#" +const USAGE: &str = r#" Parity Ethereum keys generator. Copyright 2015-2020 Parity Technologies (UK) Ltd. @@ -101,42 +148,42 @@ enum Error { impl From for Error { fn from(err: EthkeyError) -> Self { - Error::Ethkey(err) + Self::Ethkey(err) } } impl From for Error { fn from(err: FromHexError) -> Self { - Error::FromHex(err) + Self::FromHex(err) } } impl From for Error { fn from(err: ParseIntError) -> Self { - Error::ParseInt(err) + Self::ParseInt(err) } } impl From for Error { fn from(err: docopt::Error) -> Self { - Error::Docopt(err) + Self::Docopt(err) } } impl From for Error { fn from(err: io::Error) -> Self { - Error::Io(err) + Self::Io(err) } } impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - match *self { - Error::Ethkey(ref e) => write!(f, "{}", e), - Error::FromHex(ref e) => write!(f, "{}", e), - Error::ParseInt(ref e) => write!(f, "{}", e), - Error::Docopt(ref e) => write!(f, "{}", e), - Error::Io(ref e) => write!(f, "{}", e), + match self { + Self::Ethkey(e) => write!(f, "{}", e), + Self::FromHex(e) => write!(f, "{}", e), + Self::ParseInt(e) => write!(f, "{}", e), + Self::Docopt(e) => write!(f, "{}", e), + Self::Io(e) => write!(f, "{}", e), } } } @@ -151,13 +198,13 @@ enum DisplayMode { impl DisplayMode { fn new(args: &Args) -> Self { if args.flag_secret { - DisplayMode::Secret + Self::Secret } else if args.flag_public { - DisplayMode::Public + Self::Public } else if args.flag_address { - DisplayMode::Address + Self::Address } else { - DisplayMode::KeyPair + Self::KeyPair } } } @@ -168,7 +215,7 @@ fn main() { match execute(env::args()) { Ok(ok) => println!("{}", ok), - Err(Error::Docopt(ref e)) => e.exit(), + Err(Error::Docopt(e)) => e.exit(), Err(err) => { eprintln!("{}", err); process::exit(1); @@ -179,9 +226,12 @@ fn main() { fn display(result: (KeyPair, Option), mode: DisplayMode) -> String { let keypair = result.0; match mode { - DisplayMode::KeyPair => match result.1 { - Some(extra_data) => format!("{}\n{}", extra_data, keypair), - None => format!("{}", keypair) + DisplayMode::KeyPair => { + if let Some(extra_data) = result.1 { + format!("{}\n{}", extra_data, keypair) + } else { + keypair.to_string() + } }, DisplayMode::Secret => format!("{:x}", keypair.secret()), DisplayMode::Public => format!("{:x}", keypair.public()), @@ -193,7 +243,7 @@ fn execute(command: I) -> Result where I: IntoIterator(command: I) -> Result where I: IntoIterator(command: I) -> Result where I: IntoIterator(command: I) -> Result where I: IntoIterator= 1024 { + if i >= 1023 { return Ok(None) } } @@ -286,7 +333,7 @@ fn execute(command: I) -> Result where I: IntoIterator String { match Brain::validate_phrase(phrase, BRAIN_WORDS) { - Ok(()) => format!("The recovery phrase looks correct.\n"), + Ok(()) => "The recovery phrase looks correct.\n".to_string(), Err(err) => format!("The recover phrase was not generated by Parity: {}", err) } } fn in_threads(prepare: F) -> Result where O: Send + 'static, - X: Send + 'static, F: Fn() -> X, - X: FnMut() -> Result, EthkeyError>, + X: FnMut() -> Result, EthkeyError> + Send + 'static, { let pool = threadpool::Builder::new().build(); diff --git a/accounts/ethkey/src/brain.rs b/accounts/ethkey/src/brain.rs index 03c12f46ec0..e288b4694c6 100644 --- a/accounts/ethkey/src/brain.rs +++ b/accounts/ethkey/src/brain.rs @@ -23,8 +23,8 @@ use parity_wordlist; pub struct Brain(String); impl Brain { - pub fn new(s: String) -> Self { - Brain(s) + pub const fn new(s: String) -> Self { + Self(s) } pub fn validate_phrase(phrase: &str, expected_words: usize) -> Result<(), ::WordlistError> { @@ -43,18 +43,15 @@ impl Generator for Brain { loop { secret = secret.keccak256(); - match i > 16384 { - false => i += 1, - true => { - if let Ok(pair) = Secret::import_key(&secret) - .and_then(KeyPair::from_secret) - { - if pair.address()[0] == 0 { - trace!("Testing: {}, got: {:?}", self.0, pair.address()); - return Ok(pair) - } - } - }, + if i <= 16384 { + i += 1 + } else if let Ok(pair) = Secret::import_key(&secret) + .and_then(KeyPair::from_secret) + { + if pair.address()[0] == 0 { + trace!("Testing: {}, got: {:?}", self.0, pair.address()); + return Ok(pair) + } } } } @@ -69,7 +66,7 @@ mod tests { fn test_brain() { let words = "this is sparta!".to_owned(); let first_keypair = Brain::new(words.clone()).generate().unwrap(); - let second_keypair = Brain::new(words.clone()).generate().unwrap(); + let second_keypair = Brain::new(words).generate().unwrap(); assert_eq!(first_keypair.secret(), second_keypair.secret()); } } diff --git a/accounts/ethkey/src/brain_prefix.rs b/accounts/ethkey/src/brain_prefix.rs index 1fdd753fb5d..5873f5fd6ca 100644 --- a/accounts/ethkey/src/brain_prefix.rs +++ b/accounts/ethkey/src/brain_prefix.rs @@ -27,8 +27,8 @@ pub struct BrainPrefix { } impl BrainPrefix { - pub fn new(prefix: Vec, iterations: usize, no_of_words: usize) -> Self { - BrainPrefix { + pub const fn new(prefix: Vec, iterations: usize, no_of_words: usize) -> Self { + Self { prefix, iterations, no_of_words, @@ -65,7 +65,7 @@ mod tests { #[test] fn prefix_generator() { - let prefix = vec![0x00u8]; + let prefix = vec![0x00_u8]; let keypair = BrainPrefix::new(prefix.clone(), usize::max_value(), 12).generate().unwrap(); assert!(keypair.address().as_bytes().starts_with(&prefix)); } diff --git a/accounts/ethkey/src/brain_recover.rs b/accounts/ethkey/src/brain_recover.rs index e9673c843e2..8def693bfe8 100644 --- a/accounts/ethkey/src/brain_recover.rs +++ b/accounts/ethkey/src/brain_recover.rs @@ -82,20 +82,20 @@ impl PhrasesIterator { let to_add = expected_words - words.len(); info!("Number of words is insuficcient adding {} more.", to_add); for _ in 0..to_add { - words.push(parity_wordlist::WORDS.iter().cloned().collect()); + words.push(parity_wordlist::WORDS.to_vec()); } } // start searching - PhrasesIterator::new(words) + Self::new(words) } pub fn new(words: Vec>) -> Self { - let combinations = words.iter().fold(1u64, |acc, x| acc * x.len() as u64); + let combinations = words.iter().fold(1_u64, |acc, x| acc * x.len() as u64); let indexes = words.iter().map(|_| 0).collect(); info!("Starting to test {} possible combinations.", combinations); - PhrasesIterator { + Self { words, combinations, indexes, @@ -103,7 +103,7 @@ impl PhrasesIterator { } } - pub fn combinations(&self) -> u64 { + pub const fn combinations(&self) -> u64 { self.combinations } diff --git a/accounts/ethkey/src/lib.rs b/accounts/ethkey/src/lib.rs index a6e8f9a36b4..7a08758c1b2 100644 --- a/accounts/ethkey/src/lib.rs +++ b/accounts/ethkey/src/lib.rs @@ -14,7 +14,55 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . -// #![warn(missing_docs)] +#![warn(missing_docs)] + +#![warn( + clippy::all, + clippy::pedantic, + clippy::nursery, +)] +#![allow( + clippy::blacklisted_name, + clippy::cast_lossless, + clippy::cast_possible_truncation, + clippy::cast_possible_wrap, + clippy::cast_precision_loss, + clippy::cast_ptr_alignment, + clippy::cast_sign_loss, + clippy::cognitive_complexity, + clippy::default_trait_access, + clippy::enum_glob_use, + clippy::eval_order_dependence, + clippy::fallible_impl_from, + clippy::float_cmp, + clippy::identity_op, + clippy::if_not_else, + clippy::indexing_slicing, + clippy::inline_always, + clippy::items_after_statements, + clippy::large_enum_variant, + clippy::many_single_char_names, + clippy::match_same_arms, + clippy::missing_errors_doc, + clippy::missing_safety_doc, + clippy::module_inception, + clippy::module_name_repetitions, + clippy::must_use_candidate, + clippy::needless_pass_by_value, + clippy::needless_update, + clippy::non_ascii_literal, + clippy::option_option, + clippy::pub_enum_variant_names, + clippy::same_functions_in_if_condition, + clippy::shadow_unrelated, + clippy::similar_names, + clippy::single_component_path_imports, + clippy::too_many_arguments, + clippy::too_many_lines, + clippy::type_complexity, + clippy::unused_self, + clippy::used_underscore_binding, +)] extern crate edit_distance; extern crate parity_crypto; diff --git a/accounts/ethkey/src/password.rs b/accounts/ethkey/src/password.rs index 87fe61581a3..cc8f229e716 100644 --- a/accounts/ethkey/src/password.rs +++ b/accounts/ethkey/src/password.rs @@ -47,13 +47,13 @@ impl Drop for Password { } impl From for Password { - fn from(s: String) -> Password { - Password(s) + fn from(s: String) -> Self { + Self(s) } } impl<'a> From<&'a str> for Password { - fn from(s: &'a str) -> Password { - Password::from(String::from(s)) + fn from(s: &'a str) -> Self { + Self::from(String::from(s)) } } diff --git a/accounts/ethkey/src/prefix.rs b/accounts/ethkey/src/prefix.rs index 1e4d42c0f9b..943984d9e37 100644 --- a/accounts/ethkey/src/prefix.rs +++ b/accounts/ethkey/src/prefix.rs @@ -23,10 +23,10 @@ pub struct Prefix { } impl Prefix { - pub fn new(prefix: Vec, iterations: usize) -> Self { - Prefix { - prefix: prefix, - iterations: iterations, + pub const fn new(prefix: Vec, iterations: usize) -> Self { + Self { + prefix, + iterations, } } } @@ -53,7 +53,7 @@ mod tests { #[test] fn prefix_generator() { - let prefix = vec![0xffu8]; + let prefix = vec![0xff_u8]; let keypair = Prefix::new(prefix.clone(), usize::max_value()).generate().unwrap(); assert!(keypair.address().as_bytes().starts_with(&prefix)); } diff --git a/accounts/ethstore/cli/src/main.rs b/accounts/ethstore/cli/src/main.rs index a71830d75ee..608261ee38f 100644 --- a/accounts/ethstore/cli/src/main.rs +++ b/accounts/ethstore/cli/src/main.rs @@ -14,6 +14,54 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . +#![warn( + clippy::all, + clippy::pedantic, + clippy::nursery, +)] +#![allow( + clippy::blacklisted_name, + clippy::cast_lossless, + clippy::cast_possible_truncation, + clippy::cast_possible_wrap, + clippy::cast_precision_loss, + clippy::cast_ptr_alignment, + clippy::cast_sign_loss, + clippy::cognitive_complexity, + clippy::default_trait_access, + clippy::enum_glob_use, + clippy::eval_order_dependence, + clippy::fallible_impl_from, + clippy::float_cmp, + clippy::identity_op, + clippy::if_not_else, + clippy::indexing_slicing, + clippy::inline_always, + clippy::items_after_statements, + clippy::large_enum_variant, + clippy::many_single_char_names, + clippy::match_same_arms, + clippy::missing_errors_doc, + clippy::missing_safety_doc, + clippy::module_inception, + clippy::module_name_repetitions, + clippy::must_use_candidate, + clippy::needless_pass_by_value, + clippy::needless_update, + clippy::non_ascii_literal, + clippy::option_option, + clippy::pub_enum_variant_names, + clippy::same_functions_in_if_condition, + clippy::shadow_unrelated, + clippy::similar_names, + clippy::single_component_path_imports, + clippy::too_many_arguments, + clippy::too_many_lines, + clippy::type_complexity, + clippy::unused_self, + clippy::used_underscore_binding, +)] + extern crate dir; extern crate docopt; extern crate ethstore; @@ -42,7 +90,7 @@ use ethstore::{EthStore, SimpleSecretStore, SecretStore, import_accounts, Presal mod crack; -pub const USAGE: &'static str = r#" +pub const USAGE: &str = r#" Parity Ethereum key management tool. Copyright 2015-2020 Parity Technologies (UK) Ltd. @@ -130,21 +178,21 @@ enum Error { impl From for Error { fn from(err: ethstore::Error) -> Self { - Error::Ethstore(err) + Self::Ethstore(err) } } impl From for Error { fn from(err: docopt::Error) -> Self { - Error::Docopt(err) + Self::Docopt(err) } } impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - Error::Ethstore(ref err) => fmt::Display::fmt(err, f), - Error::Docopt(ref err) => fmt::Display::fmt(err, f), + match self { + Self::Ethstore(err) => fmt::Display::fmt(err, f), + Self::Docopt(err) => fmt::Display::fmt(err, f), } } } @@ -158,7 +206,7 @@ fn main() { match execute(env::args()) { Ok(result) => println!("{}", result), - Err(Error::Docopt(ref e)) => e.exit(), + Err(Error::Docopt(e)) => e.exit(), Err(err) => { eprintln!("{}", err); process::exit(1); @@ -225,7 +273,7 @@ fn execute(command: I) -> Result where I: IntoIterator(command: I) -> Result where I: IntoIterator = accounts + let accounts = accounts .into_iter() - .filter(|a| &a.vault == &vault_ref) - .map(|a| a.address) - .collect(); + .filter_map(|a| if a.vault == vault_ref { Some(a.address) } else { None }) + .collect::>(); Ok(format_accounts(&accounts)) } else if args.cmd_import { let password = match args.arg_password.as_ref() { @@ -268,7 +315,7 @@ fn execute(command: I) -> Result where I: IntoIterator>(); crack::run(passwords, &args.arg_path)?; - Ok(format!("Password not found.")) + Ok("Password not found.".to_string()) } else if args.cmd_remove { let address = args.arg_address.parse().map_err(|_| ethstore::Error::InvalidAccount)?; let password = load_password(&args.arg_password)?; @@ -315,6 +362,6 @@ fn execute(command: I) -> Result where I: IntoIterator for Aes128Ctr { fn from(json: json::Aes128Ctr) -> Self { - Aes128Ctr { + Self { iv: json.iv.into() } } @@ -45,7 +45,7 @@ impl Into for Aes128Ctr { impl From for Cipher { fn from(json: json::Cipher) -> Self { match json { - json::Cipher::Aes128Ctr(params) => Cipher::Aes128Ctr(From::from(params)), + json::Cipher::Aes128Ctr(params) => Self::Aes128Ctr(From::from(params)), } } } @@ -53,7 +53,7 @@ impl From for Cipher { impl Into for Cipher { fn into(self) -> json::Cipher { match self { - Cipher::Aes128Ctr(params) => json::Cipher::Aes128Ctr(params.into()), + Self::Aes128Ctr(params) => json::Cipher::Aes128Ctr(params.into()), } } } diff --git a/accounts/ethstore/src/account/crypto.rs b/accounts/ethstore/src/account/crypto.rs index faa04e645d6..26398c1c291 100644 --- a/accounts/ethstore/src/account/crypto.rs +++ b/accounts/ethstore/src/account/crypto.rs @@ -38,7 +38,7 @@ pub struct Crypto { impl From for Crypto { fn from(json: json::Crypto) -> Self { - Crypto { + Self { cipher: json.cipher.into(), ciphertext: json.ciphertext.into(), kdf: json.kdf.into(), @@ -49,7 +49,7 @@ impl From for Crypto { impl From for json::Crypto { fn from(c: Crypto) -> Self { - json::Crypto { + Self { cipher: c.cipher.into(), ciphertext: c.ciphertext.into(), kdf: c.kdf.into(), @@ -75,7 +75,7 @@ impl From for String { impl Crypto { /// Encrypt account secret pub fn with_secret(secret: &Secret, password: &Password, iterations: u32) -> Result { - Crypto::with_plain(secret.as_ref(), password, iterations) + Self::with_plain(secret.as_ref(), password, iterations) } /// Encrypt custom plain data @@ -99,9 +99,9 @@ impl Crypto { // KECCAK(DK[16..31] ++ ), where DK[16..31] - derived_right_bits let mac = crypto::derive_mac(&derived_right_bits, &*ciphertext).keccak256(); - Ok(Crypto { + Ok(Self { cipher: Cipher::Aes128Ctr(Aes128Ctr { - iv: iv, + iv, }), ciphertext: ciphertext.into_vec(), kdf: Kdf::Pbkdf2(Pbkdf2 { @@ -110,7 +110,7 @@ impl Crypto { c: iterations, prf: Prf::HmacSha256, }), - mac: mac, + mac, }) } @@ -131,9 +131,9 @@ impl Crypto { } fn do_decrypt(&self, password: &Password, expected_len: usize) -> Result, Error> { - let (derived_left_bits, derived_right_bits) = match self.kdf { - Kdf::Pbkdf2(ref params) => crypto::derive_key_iterations(password.as_bytes(), ¶ms.salt, params.c), - Kdf::Scrypt(ref params) => crypto::scrypt::derive_key(password.as_bytes(), ¶ms.salt, params.n, params.p, params.r)?, + let (derived_left_bits, derived_right_bits) = match &self.kdf { + Kdf::Pbkdf2(params) => crypto::derive_key_iterations(password.as_bytes(), ¶ms.salt, params.c), + Kdf::Scrypt(params) => crypto::scrypt::derive_key(password.as_bytes(), ¶ms.salt, params.n, params.p, params.r)?, }; let mac = crypto::derive_mac(&derived_right_bits, &self.ciphertext).keccak256(); @@ -144,8 +144,8 @@ impl Crypto { let mut plain: SmallVec<[u8; 32]> = SmallVec::from_vec(vec![0; expected_len]); - match self.cipher { - Cipher::Aes128Ctr(ref params) => { + match &self.cipher { + Cipher::Aes128Ctr(params) => { // checker by callers debug_assert!(expected_len >= self.ciphertext.len()); diff --git a/accounts/ethstore/src/account/kdf.rs b/accounts/ethstore/src/account/kdf.rs index fd797829a92..6113697259c 100644 --- a/accounts/ethstore/src/account/kdf.rs +++ b/accounts/ethstore/src/account/kdf.rs @@ -47,7 +47,7 @@ pub enum Kdf { impl From for Prf { fn from(json: json::Prf) -> Self { match json { - json::Prf::HmacSha256 => Prf::HmacSha256, + json::Prf::HmacSha256 => Self::HmacSha256, } } } @@ -55,14 +55,14 @@ impl From for Prf { impl Into for Prf { fn into(self) -> json::Prf { match self { - Prf::HmacSha256 => json::Prf::HmacSha256, + Self::HmacSha256 => json::Prf::HmacSha256, } } } impl From for Pbkdf2 { fn from(json: json::Pbkdf2) -> Self { - Pbkdf2 { + Self { c: json.c, dklen: json.dklen, prf: From::from(json.prf), @@ -84,7 +84,7 @@ impl Into for Pbkdf2 { impl From for Scrypt { fn from(json: json::Scrypt) -> Self { - Scrypt { + Self { dklen: json.dklen, p: json.p, n: json.n, @@ -109,8 +109,8 @@ impl Into for Scrypt { impl From for Kdf { fn from(json: json::Kdf) -> Self { match json { - json::Kdf::Pbkdf2(params) => Kdf::Pbkdf2(From::from(params)), - json::Kdf::Scrypt(params) => Kdf::Scrypt(From::from(params)), + json::Kdf::Pbkdf2(params) => Self::Pbkdf2(From::from(params)), + json::Kdf::Scrypt(params) => Self::Scrypt(From::from(params)), } } } @@ -118,8 +118,8 @@ impl From for Kdf { impl Into for Kdf { fn into(self) -> json::Kdf { match self { - Kdf::Pbkdf2(params) => json::Kdf::Pbkdf2(params.into()), - Kdf::Scrypt(params) => json::Kdf::Scrypt(params.into()), + Self::Pbkdf2(params) => json::Kdf::Pbkdf2(params.into()), + Self::Scrypt(params) => json::Kdf::Scrypt(params.into()), } } } diff --git a/accounts/ethstore/src/account/safe_account.rs b/accounts/ethstore/src/account/safe_account.rs index 691b41b9604..370f455567e 100644 --- a/accounts/ethstore/src/account/safe_account.rs +++ b/accounts/ethstore/src/account/safe_account.rs @@ -48,8 +48,8 @@ impl Into for SafeAccount { version: self.version.into(), address: Some(self.address.into()), crypto: self.crypto.into(), - name: Some(self.name.into()), - meta: Some(self.meta.into()), + name: Some(self.name), + meta: Some(self.meta), } } } @@ -64,14 +64,14 @@ impl SafeAccount { name: String, meta: String ) -> Result { - Ok(SafeAccount { - id: id, + Ok(Self { + id, version: Version::V3, crypto: Crypto::with_secret(keypair.secret(), password, iterations)?, address: keypair.address(), filename: None, - name: name, - meta: meta, + name, + meta, }) } @@ -85,35 +85,32 @@ impl SafeAccount { let crypto = Crypto::from(json.crypto); let address = match (password, &json.address) { (None, Some(json_address)) => json_address.into(), - (None, None) => Err(Error::Custom( - "This keystore does not contain address. You need to provide password to import it".into()))?, + (None, None) => return Err(Error::Custom( + "This keystore does not contain address. You need to provide password to import it".into())), (Some(password), json_address) => { let derived_address = KeyPair::from_secret( - crypto.secret(&password).map_err(|_| Error::InvalidPassword)? + crypto.secret(password).map_err(|_| Error::InvalidPassword)? )?.address(); - match json_address { - Some(json_address) => { - let json_address = json_address.into(); - if derived_address != json_address { - warn!("Detected address mismatch when opening an account. Derived: {:?}, in json got: {:?}", - derived_address, json_address); - } - }, - _ => {}, + if let Some(json_address) = json_address { + let json_address = json_address.into(); + if derived_address != json_address { + warn!("Detected address mismatch when opening an account. Derived: {:?}, in json got: {:?}", + derived_address, json_address); + } } derived_address } }; - Ok(SafeAccount { + Ok(Self { id: json.id.into(), version: json.version.into(), address, crypto, filename, - name: json.name.unwrap_or(String::new()), - meta: json.meta.unwrap_or("{}".to_owned()), + name: json.name.unwrap_or_default(), + meta: json.meta.unwrap_or_else(|| "{}".to_string()), }) } @@ -125,7 +122,7 @@ impl SafeAccount { let meta_plain = meta_crypto.decrypt(password)?; let meta_plain = json::VaultKeyMeta::load(&meta_plain).map_err(|e| Error::Custom(format!("{:?}", e)))?; - SafeAccount::from_file(json::KeyFile { + Self::from_file(json::KeyFile { id: json.id, version: json.version, crypto: json.crypto, @@ -174,17 +171,17 @@ impl SafeAccount { /// Derive public key. pub fn public(&self, password: &Password) -> Result { let secret = self.crypto.secret(password)?; - Ok(KeyPair::from_secret(secret)?.public().clone()) + Ok(*KeyPair::from_secret(secret)?.public()) } /// Change account's password. pub fn change_password(&self, old_password: &Password, new_password: &Password, iterations: u32) -> Result { let secret = self.crypto.secret(old_password)?; - let result = SafeAccount { - id: self.id.clone(), + let result = Self { + id: self.id, version: self.version.clone(), crypto: Crypto::with_secret(&secret, new_password, iterations)?, - address: self.address.clone(), + address: self.address, filename: self.filename.clone(), name: self.name.clone(), meta: self.meta.clone(), @@ -208,7 +205,7 @@ mod tests { let keypair = Random.generate().unwrap(); let password = "hello world".into(); let message = Message::default(); - let account = SafeAccount::create(&keypair, [0u8; 16], &password, 10240, "Test".to_owned(), "{}".to_owned()); + let account = SafeAccount::create(&keypair, [0_u8; 16], &password, 10240, "Test".to_owned(), "{}".to_owned()); let signature = account.unwrap().sign(&password, &message).unwrap(); assert!(verify_public(keypair.public(), &signature, &message).unwrap()); } @@ -220,7 +217,7 @@ mod tests { let sec_password = "this is sparta".into(); let i = 10240; let message = Message::default(); - let account = SafeAccount::create(&keypair, [0u8; 16], &first_password, i, "Test".to_owned(), "{}".to_owned()).unwrap(); + let account = SafeAccount::create(&keypair, [0_u8; 16], &first_password, i, "Test".to_owned(), "{}".to_owned()).unwrap(); let new_account = account.change_password(&first_password, &sec_password, i).unwrap(); assert!(account.sign(&first_password, &message).is_ok()); assert!(account.sign(&sec_password, &message).is_err()); diff --git a/accounts/ethstore/src/account/version.rs b/accounts/ethstore/src/account/version.rs index 28afcfced62..81d4f24a1d5 100644 --- a/accounts/ethstore/src/account/version.rs +++ b/accounts/ethstore/src/account/version.rs @@ -24,7 +24,7 @@ pub enum Version { impl From for Version { fn from(json: json::Version) -> Self { match json { - json::Version::V3 => Version::V3, + json::Version::V3 => Self::V3, } } } @@ -32,7 +32,7 @@ impl From for Version { impl Into for Version { fn into(self) -> json::Version { match self { - Version::V3 => json::Version::V3, + Self::V3 => json::Version::V3, } } } diff --git a/accounts/ethstore/src/accounts_dir/disk.rs b/accounts/ethstore/src/accounts_dir/disk.rs index e587ffc52ae..a8be61cdae2 100644 --- a/accounts/ethstore/src/accounts_dir/disk.rs +++ b/accounts/ethstore/src/accounts_dir/disk.rs @@ -25,7 +25,7 @@ use super::{KeyDirectory, VaultKeyDirectory, VaultKeyDirectoryProvider, VaultKey use super::vault::{VAULT_FILE_NAME, VaultDiskDirectory}; use ethkey::Password; -const IGNORED_FILES: &'static [&'static str] = &[ +const IGNORED_FILES: &[&str] = &[ "thumbs.db", "address_book.json", "dapps_policy.json", @@ -141,28 +141,33 @@ impl RootDiskDirectory { impl DiskDirectory where T: KeyFileManager { /// Create new disk directory instance pub fn new

(path: P, key_manager: T) -> Self where P: AsRef { - DiskDirectory { + Self { path: path.as_ref().to_path_buf(), - key_manager: key_manager, + key_manager, } } fn files(&self) -> Result, Error> { Ok(fs::read_dir(&self.path)? - .flat_map(Result::ok) - .filter(|entry| { - let metadata = entry.metadata().ok(); - let file_name = entry.file_name(); - let name = file_name.to_string_lossy(); - // filter directories - metadata.map_or(false, |m| !m.is_dir()) && - // hidden files - !name.starts_with(".") && - // other ignored files - !IGNORED_FILES.contains(&&*name) + .filter_map(|entry| { + if let Ok(entry) = entry { + let metadata = entry.metadata().ok(); + let file_name = entry.file_name(); + let name = file_name.to_string_lossy(); + // filter directories + if metadata.map_or(false, |m| !m.is_dir()) && + // hidden files + !name.starts_with('.') && + // other ignored files + !IGNORED_FILES.contains(&&*name) + { + return Some(entry.path()); + } + } + + None }) - .map(|entry| entry.path()) - .collect::>() + .collect() ) } @@ -180,8 +185,8 @@ impl DiskDirectory where T: KeyFileManager { } fn last_modification_date(&self) -> Result { - use std::time::{Duration, UNIX_EPOCH}; - let duration = fs::metadata(&self.path)?.modified()?.duration_since(UNIX_EPOCH).unwrap_or(Duration::default()); + use std::time::UNIX_EPOCH; + let duration = fs::metadata(&self.path)?.modified()?.duration_since(UNIX_EPOCH).unwrap_or_default(); let timestamp = duration.as_secs() ^ (duration.subsec_nanos() as u64); Ok(timestamp) } @@ -194,7 +199,7 @@ impl DiskDirectory where T: KeyFileManager { Ok(paths .into_iter() .filter_map(|path| { - let filename = Some(path.file_name().and_then(|n| n.to_str()).expect("Keys have valid UTF8 names only.").to_owned()); + let filename = Some(path.file_name().and_then(std::ffi::OsStr::to_str).expect("Keys have valid UTF8 names only.").to_owned()); fs::File::open(path.clone()) .map_err(Into::into) .and_then(|file| self.key_manager.read(filename, file)) @@ -273,7 +278,7 @@ impl KeyDirectory for DiskDirectory where T: KeyFileManager { // and find entry with given address let to_remove = self.files_content()? .into_iter() - .find(|&(_, ref acc)| acc.id == account.id && acc.address == account.address); + .find(|(_, acc)| acc.id == account.id && acc.address == account.address); // remove it match to_remove { @@ -311,7 +316,7 @@ impl VaultKeyDirectoryProvider for DiskDirectory where T: KeyFileManager { let mut vault_file_path = path.clone(); vault_file_path.push(VAULT_FILE_NAME); if vault_file_path.is_file() { - path.file_name().and_then(|f| f.to_str()).map(|f| f.to_owned()) + path.file_name().and_then(std::ffi::OsStr::to_str).map(std::borrow::ToOwned::to_owned) } else { None } @@ -369,7 +374,7 @@ mod test { let directory = RootDiskDirectory::create(dir.clone()).unwrap(); // when - let account = SafeAccount::create(&keypair, [0u8; 16], &password, 1024, "Test".to_owned(), "{}".to_owned()); + let account = SafeAccount::create(&keypair, [0_u8; 16], &password, 1024, "Test".to_owned(), "{}".to_owned()); let res = directory.insert(account.unwrap()); // then @@ -390,14 +395,14 @@ mod test { let directory = RootDiskDirectory::create(dir.clone()).unwrap(); // when - let account = SafeAccount::create(&keypair, [0u8; 16], &password, 1024, "Test".to_owned(), "{}".to_owned()).unwrap(); + let account = SafeAccount::create(&keypair, [0_u8; 16], &password, 1024, "Test".to_owned(), "{}".to_owned()).unwrap(); let filename = "test".to_string(); let dedup = true; directory.insert_with_filename(account.clone(), "foo".to_string(), dedup).unwrap(); let file1 = directory.insert_with_filename(account.clone(), filename.clone(), dedup).unwrap().filename.unwrap(); let file2 = directory.insert_with_filename(account.clone(), filename.clone(), dedup).unwrap().filename.unwrap(); - let file3 = directory.insert_with_filename(account.clone(), filename.clone(), dedup).unwrap().filename.unwrap(); + let file3 = directory.insert_with_filename(account, filename.clone(), dedup).unwrap().filename.unwrap(); // then // the first file should have the original names @@ -469,12 +474,12 @@ mod test { let hash = directory.files_hash().expect("Files hash should be calculated ok"); assert_eq!( hash, - 15130871412783076140 + 15_130_871_412_783_076_140 ); let keypair = Random.generate().unwrap(); let password = "test pass".into(); - let account = SafeAccount::create(&keypair, [0u8; 16], &password, 1024, "Test".to_owned(), "{}".to_owned()); + let account = SafeAccount::create(&keypair, [0_u8; 16], &password, 1024, "Test".to_owned(), "{}".to_owned()); directory.insert(account.unwrap()).expect("Account should be inserted ok"); let new_hash = directory.files_hash().expect("New files hash should be calculated ok"); diff --git a/accounts/ethstore/src/accounts_dir/memory.rs b/accounts/ethstore/src/accounts_dir/memory.rs index 9242bd318b5..688655bd80c 100644 --- a/accounts/ethstore/src/accounts_dir/memory.rs +++ b/accounts/ethstore/src/accounts_dir/memory.rs @@ -66,9 +66,9 @@ impl KeyDirectory for MemoryDirectory { } fn unique_repr(&self) -> Result { - let mut val = 0u64; + let mut val = 0_u64; let accounts = self.accounts.read(); - for acc in accounts.keys() { val = val ^ acc.to_low_u64_be() } + for acc in accounts.keys() { val ^= acc.to_low_u64_be() } Ok(val) } } diff --git a/accounts/ethstore/src/accounts_dir/mod.rs b/accounts/ethstore/src/accounts_dir/mod.rs index 8a4b182f237..c8fccfb52a1 100644 --- a/accounts/ethstore/src/accounts_dir/mod.rs +++ b/accounts/ethstore/src/accounts_dir/mod.rs @@ -97,9 +97,9 @@ pub use self::vault::VaultDiskDirectory; impl VaultKey { /// Create new vault key pub fn new(password: &Password, iterations: u32) -> Self { - VaultKey { + Self { password: password.clone(), - iterations: iterations, + iterations, } } } diff --git a/accounts/ethstore/src/accounts_dir/vault.rs b/accounts/ethstore/src/accounts_dir/vault.rs index 0b61358dee3..022dcae6076 100644 --- a/accounts/ethstore/src/accounts_dir/vault.rs +++ b/accounts/ethstore/src/accounts_dir/vault.rs @@ -24,9 +24,9 @@ use super::{KeyDirectory, VaultKeyDirectory, VaultKey, SetKeyError}; use super::disk::{self, DiskDirectory, KeyFileManager}; /// Name of vault metadata file -pub const VAULT_FILE_NAME: &'static str = "vault.json"; +pub const VAULT_FILE_NAME: &str = "vault.json"; /// Name of temporary vault metadata file -pub const VAULT_TEMP_FILE_NAME: &'static str = "vault_temp.json"; +pub const VAULT_TEMP_FILE_NAME: &str = "vault_temp.json"; /// Vault directory implementation pub type VaultDiskDirectory = DiskDirectory; @@ -84,7 +84,7 @@ impl VaultDiskDirectory { read_vault_file(&vault_dir_path, None) } - fn create_temp_vault(&self, key: VaultKey) -> Result { + fn create_temp_vault(&self, key: VaultKey) -> Result { let original_path = self.path().expect("self is instance of DiskDirectory; DiskDirectory always returns path; qed"); let mut path: PathBuf = original_path.clone(); let name = self.name(); @@ -96,14 +96,14 @@ impl VaultDiskDirectory { let name = format!("{}_temp_{}", name, index); path.set_file_name(&name); if !path.exists() { - return VaultDiskDirectory::create(original_path, &name, key); + return Self::create(original_path, &name, key); } index += 1; } } - fn copy_to_vault(&self, vault: &VaultDiskDirectory) -> Result<(), Error> { + fn copy_to_vault(&self, vault: &Self) -> Result<(), Error> { for account in self.load()? { let filename = account.filename.clone().expect("self is instance of DiskDirectory; DiskDirectory fills filename in load; qed"); vault.insert_with_filename(account, filename, true)?; @@ -132,7 +132,7 @@ impl VaultKeyDirectory for VaultDiskDirectory { } fn set_key(&self, new_key: VaultKey) -> Result<(), SetKeyError> { - let temp_vault = VaultDiskDirectory::create_temp_vault(self, new_key.clone()).map_err(|err| SetKeyError::NonFatalOld(err))?; + let temp_vault = Self::create_temp_vault(self, new_key).map_err(SetKeyError::NonFatalOld)?; let mut source_path = temp_vault.path().expect("temp_vault is instance of DiskDirectory; DiskDirectory always returns path; qed").clone(); let mut target_path = self.path().expect("self is instance of DiskDirectory; DiskDirectory always returns path; qed").clone(); @@ -164,7 +164,7 @@ impl VaultKeyDirectory for VaultDiskDirectory { target_path.set_file_name(VAULT_FILE_NAME); fs::rename(source_path, target_path).map_err(|err| SetKeyError::Fatal(err.into()))?; - temp_vault.delete().map_err(|err| SetKeyError::NonFatalNew(err)) + temp_vault.delete().map_err(SetKeyError::NonFatalNew) } fn meta(&self) -> String { @@ -182,9 +182,9 @@ impl VaultKeyDirectory for VaultDiskDirectory { impl VaultKeyFileManager { pub fn new(name: &str, key: VaultKey, meta: &str) -> Self { - VaultKeyFileManager { + Self { name: name.into(), - key: key, + key, meta: Mutex::new(meta.to_owned()), } } @@ -193,7 +193,7 @@ impl VaultKeyFileManager { impl KeyFileManager for VaultKeyFileManager { fn read(&self, filename: Option, reader: T) -> Result where T: io::Read { let vault_file = json::VaultKeyFile::load(reader).map_err(|e| Error::Custom(format!("{:?}", e)))?; - let mut safe_account = SafeAccount::from_vault_file(&self.key.password, vault_file, filename.clone())?; + let mut safe_account = SafeAccount::from_vault_file(&self.key.password, vault_file, filename)?; safe_account.meta = json::insert_vault_name_to_json_meta(&safe_account.meta, &self.name) .map_err(|err| Error::Custom(format!("{:?}", err)))?; @@ -238,7 +238,7 @@ fn create_vault_file

(vault_dir_path: P, key: &VaultKey, meta: &str) -> Result let crypto = Crypto::with_plain(&password_hash, &key.password, key.iterations)?; let vault_file_path = vault_dir_path.as_ref().join(VAULT_FILE_NAME); - let temp_vault_file_name = disk::find_unique_filename_using_random_suffix(vault_dir_path.as_ref(), &VAULT_TEMP_FILE_NAME)?; + let temp_vault_file_name = disk::find_unique_filename_using_random_suffix(vault_dir_path.as_ref(), VAULT_TEMP_FILE_NAME)?; let temp_vault_file_path = vault_dir_path.as_ref().join(&temp_vault_file_name); // this method is used to rewrite existing vault file @@ -262,7 +262,7 @@ fn read_vault_file

(vault_dir_path: P, key: Option<&VaultKey>) -> Result Result<(), fmt::Error> { - let s = match *self { - Error::Io(ref err) => err.to_string(), - Error::InvalidPassword => "Invalid password".into(), - Error::InvalidSecret => "Invalid secret".into(), - Error::InvalidCryptoMeta => "Invalid crypted metadata".into(), - Error::InvalidAccount => "Invalid account".into(), - Error::InvalidMessage => "Invalid message".into(), - Error::InvalidKeyFile(ref reason) => format!("Invalid key file: {}", reason), - Error::VaultsAreNotSupported => "Vaults are not supported".into(), - Error::UnsupportedVault => "Vault is not supported for this operation".into(), - Error::InvalidVaultName => "Invalid vault name".into(), - Error::VaultNotFound => "Vault not found".into(), - Error::CreationFailed => "Account creation failed".into(), - Error::EthCrypto(ref err) => err.to_string(), - Error::EthPublicKeyCrypto(ref err) => err.to_string(), - Error::Derivation(ref err) => format!("Derivation error: {:?}", err), - Error::Custom(ref s) => s.clone(), + let s = match self { + Self::Io(err) => err.to_string(), + Self::InvalidPassword => "Invalid password".into(), + Self::InvalidSecret => "Invalid secret".into(), + Self::InvalidCryptoMeta => "Invalid crypted metadata".into(), + Self::InvalidAccount => "Invalid account".into(), + Self::InvalidMessage => "Invalid message".into(), + Self::InvalidKeyFile(reason) => format!("Invalid key file: {}", reason), + Self::VaultsAreNotSupported => "Vaults are not supported".into(), + Self::UnsupportedVault => "Vault is not supported for this operation".into(), + Self::InvalidVaultName => "Invalid vault name".into(), + Self::VaultNotFound => "Vault not found".into(), + Self::CreationFailed => "Account creation failed".into(), + Self::EthCrypto(err) => err.to_string(), + Self::EthPublicKeyCrypto(err) => err.to_string(), + Self::Derivation(err) => format!("Derivation error: {:?}", err), + Self::Custom(s) => s.clone(), }; write!(f, "{}", s) @@ -83,36 +83,36 @@ impl fmt::Display for Error { impl From for Error { fn from(err: IoError) -> Self { - Error::Io(err) + Self::Io(err) } } impl From for Error { fn from(err: EthPublicKeyCryptoError) -> Self { - Error::EthPublicKeyCrypto(err) + Self::EthPublicKeyCrypto(err) } } impl From for Error { fn from(err: EthCryptoError) -> Self { - Error::EthCrypto(err) + Self::EthCrypto(err) } } impl From for Error { fn from(err: crypto::error::ScryptError) -> Self { - Error::EthCrypto(err.into()) + Self::EthCrypto(err.into()) } } impl From for Error { fn from(err: crypto::error::SymmError) -> Self { - Error::EthCrypto(err.into()) + Self::EthCrypto(err.into()) } } impl From for Error { fn from(err: DerivationError) -> Self { - Error::Derivation(err) + Self::Derivation(err) } } diff --git a/accounts/ethstore/src/ethstore.rs b/accounts/ethstore/src/ethstore.rs index be4fe6795bf..b057d28b85b 100644 --- a/accounts/ethstore/src/ethstore.rs +++ b/accounts/ethstore/src/ethstore.rs @@ -43,7 +43,7 @@ impl EthStore { /// Open a new account store with given key directory backend and custom number of iterations. pub fn open_with_iterations(directory: Box, iterations: u32) -> Result { - Ok(EthStore { + Ok(Self { store: EthMultiStore::open_with_iterations(directory, iterations)?, }) } @@ -204,12 +204,12 @@ impl SecretStore for EthStore { fn name(&self, account: &StoreAccountRef) -> Result { let account = self.get(account)?; - Ok(account.name.clone()) + Ok(account.name) } fn meta(&self, account: &StoreAccountRef) -> Result { let account = self.get(account)?; - Ok(account.meta.clone()) + Ok(account.meta) } fn set_name(&self, account_ref: &StoreAccountRef, name: String) -> Result<(), Error> { @@ -251,7 +251,7 @@ impl SecretStore for EthStore { }; imported_addresses - .map(|a| a.into_iter().map(|a| StoreAccountRef::root(a)).collect()) + .map(|a| a.into_iter().map(StoreAccountRef::root).collect()) } } @@ -279,10 +279,10 @@ impl EthMultiStore { /// Open new multi-accounts store with given key directory backend and custom number of iterations for new keys. pub fn open_with_iterations(directory: Box, iterations: u32) -> Result { - let store = EthMultiStore { + let store = Self { dir: directory, vaults: Mutex::new(HashMap::new()), - iterations: iterations, + iterations, cache: Default::default(), timestamp: Mutex::new(Timestamp { dir_hash: None, @@ -357,12 +357,11 @@ impl EthMultiStore { None }; - match from_cache(account) { - Some(accounts) => Ok(accounts), - None => { - self.reload_if_changed()?; - from_cache(account).ok_or(Error::InvalidAccount) - } + if let Some(accounts) = from_cache(account) { + Ok(accounts) + } else { + self.reload_if_changed()?; + from_cache(account).ok_or(Error::InvalidAccount) } } @@ -377,13 +376,13 @@ impl EthMultiStore { fn import(&self, vault: SecretVaultRef, account: SafeAccount) -> Result { // save to file - let account = match vault { + let account = match &vault { SecretVaultRef::Root => self.dir.insert(account)?, - SecretVaultRef::Vault(ref vault_name) => self.vaults.lock().get_mut(vault_name).ok_or(Error::VaultNotFound)?.insert(account)?, + SecretVaultRef::Vault(vault_name) => self.vaults.lock().get_mut(vault_name).ok_or(Error::VaultNotFound)?.insert(account)?, }; // update cache - let account_ref = StoreAccountRef::new(vault, account.address.clone()); + let account_ref = StoreAccountRef::new(vault, account.address); let mut cache = self.cache.write(); cache.entry(account_ref.clone()) .or_insert_with(Vec::new) @@ -394,9 +393,9 @@ impl EthMultiStore { fn update(&self, account_ref: &StoreAccountRef, old: SafeAccount, new: SafeAccount) -> Result<(), Error> { // save to file - let account = match account_ref.vault { + let account = match &account_ref.vault { SecretVaultRef::Root => self.dir.update(new)?, - SecretVaultRef::Vault(ref vault_name) => self.vaults.lock().get_mut(vault_name).ok_or(Error::VaultNotFound)?.update(new)?, + SecretVaultRef::Vault(vault_name) => self.vaults.lock().get_mut(vault_name).ok_or(Error::VaultNotFound)?.update(new)?, }; // update cache @@ -412,9 +411,9 @@ impl EthMultiStore { fn remove_safe_account(&self, account_ref: &StoreAccountRef, account: &SafeAccount) -> Result<(), Error> { // Remove from dir - match account_ref.vault { - SecretVaultRef::Root => self.dir.remove(&account)?, - SecretVaultRef::Vault(ref vault_name) => self.vaults.lock().get(vault_name).ok_or(Error::VaultNotFound)?.remove(&account)?, + match &account_ref.vault { + SecretVaultRef::Root => self.dir.remove(account)?, + SecretVaultRef::Vault(vault_name) => self.vaults.lock().get(vault_name).ok_or(Error::VaultNotFound)?.remove(account)?, }; // Remove from cache @@ -434,7 +433,7 @@ impl EthMultiStore { cache.remove(account_ref); } - return Ok(()); + Ok(()) } fn generate(&self, secret: Secret, derivation: Derivation) -> Result { @@ -467,34 +466,28 @@ impl SimpleSecretStore for EthMultiStore { -> Result { let accounts = self.get_matching(account_ref, password)?; - for account in accounts { - let extended = self.generate(account.crypto.secret(password)?, derivation)?; - return self.insert_account(vault, extended.secret().as_raw().clone(), password); - } - Err(Error::InvalidPassword) + let account = accounts.first().ok_or(Error::InvalidPassword)?; + let extended = self.generate(account.crypto.secret(password)?, derivation)?; + self.insert_account(vault, extended.secret().as_raw().clone(), password) } fn generate_derived(&self, account_ref: &StoreAccountRef, password: &Password, derivation: Derivation) -> Result { - let accounts = self.get_matching(&account_ref, password)?; - for account in accounts { - let extended = self.generate(account.crypto.secret(password)?, derivation)?; - return Ok(crypto::publickey::public_to_address(extended.public().public())); - } - Err(Error::InvalidPassword) + let accounts = self.get_matching(account_ref, password)?; + let account = accounts.first().ok_or(Error::InvalidPassword)?; + let extended = self.generate(account.crypto.secret(password)?, derivation)?; + Ok(crypto::publickey::public_to_address(extended.public().public())) } fn sign_derived(&self, account_ref: &StoreAccountRef, password: &Password, derivation: Derivation, message: &Message) -> Result { - let accounts = self.get_matching(&account_ref, password)?; - for account in accounts { - let extended = self.generate(account.crypto.secret(password)?, derivation)?; - let secret = extended.secret().as_raw(); - return Ok(crypto::publickey::sign(&secret, message)?) - } - Err(Error::InvalidPassword) + let accounts = self.get_matching(account_ref, password)?; + let account = accounts.first().ok_or(Error::InvalidPassword)?; + let extended = self.generate(account.crypto.secret(password)?, derivation)?; + let secret = extended.secret().as_raw(); + Ok(crypto::publickey::sign(secret, message)?) } fn account_ref(&self, address: &Address) -> Result { @@ -505,12 +498,11 @@ impl SimpleSecretStore for EthMultiStore { r.next().map(|(k, _)| k.clone()) }; - match read_from_cache(address) { - Some(account) => Ok(account), - None => { - self.reload_if_changed()?; - read_from_cache(address).ok_or(Error::InvalidAccount) - } + if let Some(account) = read_from_cache(address) { + Ok(account) + } else { + self.reload_if_changed()?; + read_from_cache(address).ok_or(Error::InvalidAccount) } } @@ -521,12 +513,8 @@ impl SimpleSecretStore for EthMultiStore { fn remove_account(&self, account_ref: &StoreAccountRef, password: &Password) -> Result<(), Error> { let accounts = self.get_matching(account_ref, password)?; - - for account in accounts { - return self.remove_safe_account(account_ref, &account); - } - - Err(Error::InvalidPassword) + let account = accounts.first().ok_or(Error::InvalidPassword)?; + self.remove_safe_account(account_ref, account) } fn change_password(&self, account_ref: &StoreAccountRef, old_password: &Password, new_password: &Password) -> Result<(), Error> { @@ -546,13 +534,13 @@ impl SimpleSecretStore for EthMultiStore { } fn export_account(&self, account_ref: &StoreAccountRef, password: &Password) -> Result { - self.get_matching(account_ref, password)?.into_iter().nth(0).map(Into::into).ok_or(Error::InvalidPassword) + self.get_matching(account_ref, password)?.into_iter().next().map(Into::into).ok_or(Error::InvalidPassword) } fn sign(&self, account: &StoreAccountRef, password: &Password, message: &Message) -> Result { let accounts = self.get_matching(account, password)?; match accounts.first() { - Some(ref account) => account.sign(password, message), + Some(account) => account.sign(password, message), None => Err(Error::InvalidPassword), } } @@ -560,7 +548,7 @@ impl SimpleSecretStore for EthMultiStore { fn decrypt(&self, account: &StoreAccountRef, password: &Password, shared_mac: &[u8], message: &[u8]) -> Result, Error> { let accounts = self.get_matching(account, password)?; match accounts.first() { - Some(ref account) => account.decrypt(password, shared_mac, message), + Some(account) => account.decrypt(password, shared_mac, message), None => Err(Error::InvalidPassword), } } @@ -568,7 +556,7 @@ impl SimpleSecretStore for EthMultiStore { fn agree(&self, account: &StoreAccountRef, password: &Password, other: &Public) -> Result { let accounts = self.get_matching(account, password)?; match accounts.first() { - Some(ref account) => account.agree(password, other), + Some(account) => account.agree(password, other), None => Err(Error::InvalidPassword), } } @@ -657,7 +645,7 @@ impl SimpleSecretStore for EthMultiStore { return Ok(account_ref); } - let account = self.get_accounts(&account_ref)?.into_iter().nth(0).ok_or(Error::InvalidAccount)?; + let account = self.get_accounts(&account_ref)?.into_iter().next().ok_or(Error::InvalidAccount)?; let new_account_ref = self.import(vault, account.clone())?; self.remove_safe_account(&account_ref, &account)?; self.reload_accounts()?; @@ -669,7 +657,7 @@ impl SimpleSecretStore for EthMultiStore { // => allow reading meta even if vault is not yet opened self.vaults.lock() .get(name) - .and_then(|v| Some(v.meta())) + .map(|v| v.meta()) .ok_or(Error::VaultNotFound) .or_else(|_| { let vault_provider = self.dir.as_vault_provider().ok_or(Error::VaultsAreNotSupported)?; @@ -719,7 +707,7 @@ mod tests { let temp_path = TempDir::new("").unwrap(); let disk_dir = Box::new(RootDiskDirectory::create(temp_path.path()).unwrap()); - RootDiskDirectoryGuard { + Self { key_dir: Some(disk_dir), _path: temp_path, } @@ -906,14 +894,14 @@ mod tests { let account3 = store.insert_account(SecretVaultRef::Root, keypair3.secret().clone(), &password3).unwrap(); // then - let account1 = store.change_account_vault(SecretVaultRef::Root, account1.clone()).unwrap(); - let account2 = store.change_account_vault(SecretVaultRef::Vault(name2.to_owned()), account2.clone()).unwrap(); + let account1 = store.change_account_vault(SecretVaultRef::Root, account1).unwrap(); + let account2 = store.change_account_vault(SecretVaultRef::Vault(name2.to_owned()), account2).unwrap(); let account3 = store.change_account_vault(SecretVaultRef::Vault(name2.to_owned()), account3).unwrap(); let accounts = store.accounts().unwrap(); assert_eq!(accounts.len(), 3); - assert!(accounts.iter().any(|a| a == &StoreAccountRef::root(account1.address.clone()))); - assert!(accounts.iter().any(|a| a == &StoreAccountRef::vault(name2, account2.address.clone()))); - assert!(accounts.iter().any(|a| a == &StoreAccountRef::vault(name2, account3.address.clone()))); + assert!(accounts.iter().any(|a| a == &StoreAccountRef::root(account1.address))); + assert!(accounts.iter().any(|a| a == &StoreAccountRef::vault(name2, account2.address))); + assert!(accounts.iter().any(|a| a == &StoreAccountRef::vault(name2, account3.address))); // and then assert_eq!(store.meta(&StoreAccountRef::root(account1.address)).unwrap(), r#"{}"#); @@ -1039,8 +1027,8 @@ mod tests { // then let opened_vaults = store.list_opened_vaults().unwrap(); assert_eq!(opened_vaults.len(), 2); - assert!(opened_vaults.iter().any(|v| &*v == name1)); - assert!(opened_vaults.iter().any(|v| &*v == name3)); + assert!(opened_vaults.iter().any(|v| v == name1)); + assert!(opened_vaults.iter().any(|v| v == name3)); } #[test] diff --git a/accounts/ethstore/src/import.rs b/accounts/ethstore/src/import.rs index 2426de1c0ab..2d4f406f00a 100644 --- a/accounts/ethstore/src/import.rs +++ b/accounts/ethstore/src/import.rs @@ -27,12 +27,12 @@ use Error; pub fn import_account(path: &Path, dst: &dyn KeyDirectory) -> Result { let key_manager = DiskKeyFileManager::default(); let existing_accounts = dst.load()?.into_iter().map(|a| a.address).collect::>(); - let filename = path.file_name().and_then(|n| n.to_str()).map(|f| f.to_owned()); + let filename = path.file_name().and_then(std::ffi::OsStr::to_str).map(ToOwned::to_owned); let account = fs::File::open(&path) .map_err(Into::into) .and_then(|file| key_manager.read(filename, file))?; - let address = account.address.clone(); + let address = account.address; if !existing_accounts.contains(&address) { dst.insert(account)?; } @@ -46,21 +46,22 @@ pub fn import_accounts(src: &dyn KeyDirectory, dst: &dyn KeyDirectory) -> Result .map(|a| a.address) .collect::>(); - accounts.into_iter() - .filter(|a| !existing_accounts.contains(&a.address)) - .map(|a| { - let address = a.address.clone(); - dst.insert(a)?; - Ok(address) - }).collect() + let mut out = Vec::with_capacity(accounts.len()); + for account in accounts { + let address = account.address; + if existing_accounts.contains(&address) { + dst.insert(account)?; + out.push(address); + } + } + Ok(out) } /// Provide a `HashSet` of all accounts available for import from the Geth keystore. pub fn read_geth_accounts(testnet: bool) -> Vec

{ RootDiskDirectory::at(dir::geth(testnet)) .load() - .map(|d| d.into_iter().map(|a| a.address).collect()) - .unwrap_or_else(|_| Vec::new()) + .map_or_else(|_| Vec::new(), |d| d.into_iter().map(|a| a.address).collect()) } /// Import specific `desired` accounts from the Geth keystore into `dst`. @@ -69,12 +70,14 @@ pub fn import_geth_accounts(dst: &dyn KeyDirectory, desired: HashSet
, t let accounts = src.load()?; let existing_accounts = dst.load()?.into_iter().map(|a| a.address).collect::>(); - accounts.into_iter() - .filter(|a| !existing_accounts.contains(&a.address)) - .filter(|a| desired.contains(&a.address)) - .map(|a| { - let address = a.address.clone(); - dst.insert(a)?; - Ok(address) - }).collect() + let mut out = Vec::with_capacity(accounts.len()); + for account in accounts { + let address = account.address; + if !existing_accounts.contains(&address) && desired.contains(&address) { + dst.insert(account)?; + out.push(address); + } + } + + Ok(out) } diff --git a/accounts/ethstore/src/json/bytes.rs b/accounts/ethstore/src/json/bytes.rs index 0cb00c8d3b9..68762afaa7c 100644 --- a/accounts/ethstore/src/json/bytes.rs +++ b/accounts/ethstore/src/json/bytes.rs @@ -36,7 +36,7 @@ impl<'a> Deserialize<'a> for Bytes { { let s = String::deserialize(deserializer)?; let data = s.from_hex().map_err(|e| Error::custom(format!("Invalid hex value {}", e)))?; - Ok(Bytes(data)) + Ok(Self(data)) } } @@ -51,19 +51,19 @@ impl str::FromStr for Bytes { type Err = FromHexError; fn from_str(s: &str) -> Result { - s.from_hex().map(Bytes) + s.from_hex().map(Self) } } impl From<&'static str> for Bytes { fn from(s: &'static str) -> Self { - s.parse().expect(&format!("invalid string literal for {}: '{}'", stringify!(Self), s)) + s.parse().unwrap_or_else(|e| panic!("invalid string literal for {}: '{}': {}", stringify!(Self), s, e)) } } impl From> for Bytes { fn from(v: Vec) -> Self { - Bytes(v) + Self(v) } } diff --git a/accounts/ethstore/src/json/cipher.rs b/accounts/ethstore/src/json/cipher.rs index d5acc75f8a3..c7b97ac2ba7 100644 --- a/accounts/ethstore/src/json/cipher.rs +++ b/accounts/ethstore/src/json/cipher.rs @@ -27,8 +27,8 @@ pub enum CipherSer { impl Serialize for CipherSer { fn serialize(&self, serializer: S) -> Result where S: Serializer { - match *self { - CipherSer::Aes128Ctr => serializer.serialize_str("aes-128-ctr"), + match self { + Self::Aes128Ctr => serializer.serialize_str("aes-128-ctr"), } } } @@ -74,8 +74,8 @@ pub enum CipherSerParams { impl Serialize for CipherSerParams { fn serialize(&self, serializer: S) -> Result where S: Serializer { - match *self { - CipherSerParams::Aes128Ctr(ref params) => params.serialize(serializer), + match self { + Self::Aes128Ctr(params) => params.serialize(serializer), } } } @@ -84,7 +84,7 @@ impl<'a> Deserialize<'a> for CipherSerParams { fn deserialize(deserializer: D) -> Result where D: Deserializer<'a> { Aes128Ctr::deserialize(deserializer) - .map(CipherSerParams::Aes128Ctr) + .map(Self::Aes128Ctr) .map_err(|_| Error::InvalidCipherParams) .map_err(SerdeError::custom) } diff --git a/accounts/ethstore/src/json/crypto.rs b/accounts/ethstore/src/json/crypto.rs index b1736df02c4..af1c2225f06 100644 --- a/accounts/ethstore/src/json/crypto.rs +++ b/accounts/ethstore/src/json/crypto.rs @@ -56,7 +56,7 @@ enum CryptoField { } impl<'a> Deserialize<'a> for CryptoField { - fn deserialize(deserializer: D) -> Result + fn deserialize(deserializer: D) -> Result where D: Deserializer<'a> { deserializer.deserialize_any(CryptoFieldVisitor) @@ -89,10 +89,10 @@ impl<'a> Visitor<'a> for CryptoFieldVisitor { } impl<'a> Deserialize<'a> for Crypto { - fn deserialize(deserializer: D) -> Result + fn deserialize(deserializer: D) -> Result where D: Deserializer<'a> { - static FIELDS: &'static [&'static str] = &["id", "version", "crypto", "Crypto", "address"]; + static FIELDS: &[&str] = &["id", "version", "crypto", "Crypto", "address"]; deserializer.deserialize_struct("Crypto", FIELDS, CryptoVisitor) } } @@ -155,10 +155,10 @@ impl<'a> Visitor<'a> for CryptoVisitor { }; let result = Crypto { - cipher: cipher, - ciphertext: ciphertext, - kdf: kdf, - mac: mac, + cipher, + ciphertext, + kdf, + mac, }; Ok(result) @@ -170,19 +170,19 @@ impl Serialize for Crypto { where S: Serializer { let mut crypto = serializer.serialize_struct("Crypto", 6)?; - match self.cipher { - Cipher::Aes128Ctr(ref params) => { + match &self.cipher { + Cipher::Aes128Ctr(params) => { crypto.serialize_field("cipher", &CipherSer::Aes128Ctr)?; crypto.serialize_field("cipherparams", params)?; }, } crypto.serialize_field("ciphertext", &self.ciphertext)?; - match self.kdf { - Kdf::Pbkdf2(ref params) => { + match &self.kdf { + Kdf::Pbkdf2(params) => { crypto.serialize_field("kdf", &KdfSer::Pbkdf2)?; crypto.serialize_field("kdfparams", params)?; }, - Kdf::Scrypt(ref params) => { + Kdf::Scrypt(params) => { crypto.serialize_field("kdf", &KdfSer::Scrypt)?; crypto.serialize_field("kdfparams", params)?; }, diff --git a/accounts/ethstore/src/json/error.rs b/accounts/ethstore/src/json/error.rs index 7dba257e630..f90d9de6a0a 100644 --- a/accounts/ethstore/src/json/error.rs +++ b/accounts/ethstore/src/json/error.rs @@ -30,15 +30,15 @@ pub enum Error { impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - match *self { - Error::InvalidUuid => write!(f, "Invalid Uuid"), - Error::UnsupportedVersion => write!(f, "Unsupported version"), - Error::UnsupportedKdf => write!(f, "Unsupported kdf"), - Error::InvalidCiphertext => write!(f, "Invalid ciphertext"), - Error::UnsupportedCipher => write!(f, "Unsupported cipher"), - Error::InvalidCipherParams => write!(f, "Invalid cipher params"), - Error::InvalidH256 => write!(f, "Invalid hash"), - Error::InvalidPrf => write!(f, "Invalid prf"), + match self { + Self::InvalidUuid => write!(f, "Invalid Uuid"), + Self::UnsupportedVersion => write!(f, "Unsupported version"), + Self::UnsupportedKdf => write!(f, "Unsupported kdf"), + Self::InvalidCiphertext => write!(f, "Invalid ciphertext"), + Self::UnsupportedCipher => write!(f, "Unsupported cipher"), + Self::InvalidCipherParams => write!(f, "Invalid cipher params"), + Self::InvalidH256 => write!(f, "Invalid hash"), + Self::InvalidPrf => write!(f, "Invalid prf"), } } } diff --git a/accounts/ethstore/src/json/hash.rs b/accounts/ethstore/src/json/hash.rs index 1a699367a24..39d804f4cb3 100644 --- a/accounts/ethstore/src/json/hash.rs +++ b/accounts/ethstore/src/json/hash.rs @@ -83,14 +83,15 @@ macro_rules! impl_hash { type Err = Error; fn from_str(value: &str) -> Result { - match value.from_hex() { - Ok(ref hex) if hex.len() == $size => { - let mut hash = [0u8; $size]; - hash.clone_from_slice(hex); - Ok($name(hash)) + if let Ok(hex) = value.from_hex() { + if hex.len() == $size { + let mut hash = [0_u8; $size]; + hash.copy_from_slice(&hex); + return Ok($name(hash)); } - _ => Err(Error::InvalidH256), } + + Err(Error::InvalidH256) } } diff --git a/accounts/ethstore/src/json/id.rs b/accounts/ethstore/src/json/id.rs index 0da0a3b83a0..af1407d3ca2 100644 --- a/accounts/ethstore/src/json/id.rs +++ b/accounts/ethstore/src/json/id.rs @@ -27,7 +27,7 @@ pub struct Uuid([u8; 16]); impl From<[u8; 16]> for Uuid { fn from(uuid: [u8; 16]) -> Self { - Uuid(uuid) + Self(uuid) } } @@ -56,7 +56,7 @@ impl Into<[u8; 16]> for Uuid { impl fmt::Display for Uuid { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - let s: String = (self as &Uuid).into(); + let s: String = (self as &Self).into(); write!(f, "{}", s) } } @@ -76,13 +76,13 @@ impl str::FromStr for Uuid { type Err = Error; fn from_str(s: &str) -> Result { - let parts: Vec<&str> = s.split("-").collect(); + let parts: Vec<&str> = s.split('-').collect(); if parts.len() != 5 { return Err(Error::InvalidUuid); } - let mut uuid = [0u8; 16]; + let mut uuid = [0_u8; 16]; copy_into(parts[0], &mut uuid[0..4])?; copy_into(parts[1], &mut uuid[4..6])?; @@ -90,13 +90,13 @@ impl str::FromStr for Uuid { copy_into(parts[3], &mut uuid[8..10])?; copy_into(parts[4], &mut uuid[10..16])?; - Ok(Uuid(uuid)) + Ok(Self(uuid)) } } impl From<&'static str> for Uuid { fn from(s: &'static str) -> Self { - s.parse().expect(&format!("invalid string literal for {}: '{}'", stringify!(Self), s)) + s.parse().unwrap_or_else(|e| panic!("invalid string literal for {}: '{}': {}", stringify!(Self), s, e)) } } diff --git a/accounts/ethstore/src/json/kdf.rs b/accounts/ethstore/src/json/kdf.rs index eabb49cd713..2815ba747b0 100644 --- a/accounts/ethstore/src/json/kdf.rs +++ b/accounts/ethstore/src/json/kdf.rs @@ -28,9 +28,9 @@ pub enum KdfSer { impl Serialize for KdfSer { fn serialize(&self, serializer: S) -> Result where S: Serializer { - match *self { - KdfSer::Pbkdf2 => serializer.serialize_str("pbkdf2"), - KdfSer::Scrypt => serializer.serialize_str("scrypt"), + match self { + Self::Pbkdf2 => serializer.serialize_str("pbkdf2"), + Self::Scrypt => serializer.serialize_str("scrypt"), } } } @@ -72,8 +72,8 @@ pub enum Prf { impl Serialize for Prf { fn serialize(&self, serializer: S) -> Result where S: Serializer { - match *self { - Prf::HmacSha256 => serializer.serialize_str("hmac-sha256"), + match self { + Self::HmacSha256 => serializer.serialize_str("hmac-sha256"), } } } @@ -132,9 +132,9 @@ pub enum KdfSerParams { impl Serialize for KdfSerParams { fn serialize(&self, serializer: S) -> Result where S: Serializer { - match *self { - KdfSerParams::Pbkdf2(ref params) => params.serialize(serializer), - KdfSerParams::Scrypt(ref params) => params.serialize(serializer), + match self { + Self::Pbkdf2(params) => params.serialize(serializer), + Self::Scrypt(params) => params.serialize(serializer), } } } @@ -146,8 +146,8 @@ impl<'a> Deserialize<'a> for KdfSerParams { let v: Value = Deserialize::deserialize(deserializer)?; - from_value(v.clone()).map(KdfSerParams::Pbkdf2) - .or_else(|_| from_value(v).map(KdfSerParams::Scrypt)) + from_value(v.clone()).map(Self::Pbkdf2) + .or_else(|_| from_value(v).map(Self::Scrypt)) .map_err(|_| D::Error::custom("Invalid KDF algorithm")) } } diff --git a/accounts/ethstore/src/json/key_file.rs b/accounts/ethstore/src/json/key_file.rs index 2e7a45bfa48..fb712839723 100644 --- a/accounts/ethstore/src/json/key_file.rs +++ b/accounts/ethstore/src/json/key_file.rs @@ -37,7 +37,7 @@ impl Serialize for OpaqueKeyFile { impl From for OpaqueKeyFile where T: Into { fn from(val: T) -> Self { - OpaqueKeyFile { key_file: val.into() } + Self { key_file: val.into() } } } @@ -61,7 +61,7 @@ enum KeyFileField { } impl<'a> Deserialize<'a> for KeyFileField { - fn deserialize(deserializer: D) -> Result + fn deserialize(deserializer: D) -> Result where D: Deserializer<'a> { deserializer.deserialize_any(KeyFileFieldVisitor) @@ -94,15 +94,15 @@ impl<'a> Visitor<'a> for KeyFileFieldVisitor { } impl<'a> Deserialize<'a> for KeyFile { - fn deserialize(deserializer: D) -> Result + fn deserialize(deserializer: D) -> Result where D: Deserializer<'a> { - static FIELDS: &'static [&'static str] = &["id", "version", "crypto", "Crypto", "address"]; + static FIELDS: &[&str] = &["id", "version", "crypto", "Crypto", "address"]; deserializer.deserialize_struct("KeyFile", FIELDS, KeyFileVisitor) } } -fn none_if_empty<'a, T>(v: Option) -> Option where +fn none_if_empty(v: Option) -> Option where T: DeserializeOwned { v.and_then(|v| if v.is_null() { @@ -159,12 +159,12 @@ impl<'a> Visitor<'a> for KeyFileVisitor { }; let result = KeyFile { - id: id, - version: version, - crypto: crypto, - address: address, - name: name, - meta: meta, + id, + version, + crypto, + address, + name, + meta, }; Ok(result) @@ -224,7 +224,7 @@ mod tests { }), ciphertext: "7203da0676d141b138cd7f8e1a4365f59cc1aa6978dc5443f364ca943d7cb4bc".into(), kdf: Kdf::Scrypt(Scrypt { - n: 262144, + n: 262_144, dklen: 32, p: 1, r: 8, @@ -275,7 +275,7 @@ mod tests { }), ciphertext: "7203da0676d141b138cd7f8e1a4365f59cc1aa6978dc5443f364ca943d7cb4bc".into(), kdf: Kdf::Scrypt(Scrypt { - n: 262144, + n: 262_144, dklen: 32, p: 1, r: 8, @@ -303,7 +303,7 @@ mod tests { }), ciphertext: "7203da0676d141b138cd7f8e1a4365f59cc1aa6978dc5443f364ca943d7cb4bc".into(), kdf: Kdf::Scrypt(Scrypt { - n: 262144, + n: 262_144, dklen: 32, p: 1, r: 8, diff --git a/accounts/ethstore/src/json/vault_key_file.rs b/accounts/ethstore/src/json/vault_key_file.rs index 854685e31a6..59dc7fec98c 100644 --- a/accounts/ethstore/src/json/vault_key_file.rs +++ b/accounts/ethstore/src/json/vault_key_file.rs @@ -22,7 +22,7 @@ use serde_json::error; use super::{Uuid, Version, Crypto, H160}; /// Meta key name for vault field -const VAULT_NAME_META_KEY: &'static str = "vault"; +const VAULT_NAME_META_KEY: &str = "vault"; /// Key file as stored in vaults #[derive(Debug, PartialEq, Serialize, Deserialize)] @@ -92,7 +92,7 @@ impl VaultKeyFile { impl VaultKeyMeta { pub fn load(bytes: &[u8]) -> Result { - serde_json::from_slice(&bytes) + serde_json::from_slice(bytes) } pub fn write(&self) -> Result, serde_json::Error> { diff --git a/accounts/ethstore/src/json/version.rs b/accounts/ethstore/src/json/version.rs index 583f05e8832..b83477cd03a 100644 --- a/accounts/ethstore/src/json/version.rs +++ b/accounts/ethstore/src/json/version.rs @@ -27,14 +27,14 @@ pub enum Version { impl Serialize for Version { fn serialize(&self, serializer: S) -> Result where S: Serializer { - match *self { - Version::V3 => serializer.serialize_u64(3) + match self { + Self::V3 => serializer.serialize_u64(3) } } } impl<'a> Deserialize<'a> for Version { - fn deserialize(deserializer: D) -> Result + fn deserialize(deserializer: D) -> Result where D: Deserializer<'a> { deserializer.deserialize_any(VersionVisitor) } diff --git a/accounts/ethstore/src/lib.rs b/accounts/ethstore/src/lib.rs index 0016bd41fea..9498b318eb7 100644 --- a/accounts/ethstore/src/lib.rs +++ b/accounts/ethstore/src/lib.rs @@ -18,6 +18,54 @@ #![warn(missing_docs)] +#![warn( + clippy::all, + clippy::pedantic, + clippy::nursery, +)] +#![allow( + clippy::blacklisted_name, + clippy::cast_lossless, + clippy::cast_possible_truncation, + clippy::cast_possible_wrap, + clippy::cast_precision_loss, + clippy::cast_ptr_alignment, + clippy::cast_sign_loss, + clippy::cognitive_complexity, + clippy::default_trait_access, + clippy::enum_glob_use, + clippy::eval_order_dependence, + clippy::fallible_impl_from, + clippy::float_cmp, + clippy::identity_op, + clippy::if_not_else, + clippy::indexing_slicing, + clippy::inline_always, + clippy::items_after_statements, + clippy::large_enum_variant, + clippy::many_single_char_names, + clippy::match_same_arms, + clippy::missing_errors_doc, + clippy::missing_safety_doc, + clippy::module_inception, + clippy::module_name_repetitions, + clippy::must_use_candidate, + clippy::needless_pass_by_value, + clippy::needless_update, + clippy::non_ascii_literal, + clippy::option_option, + clippy::pub_enum_variant_names, + clippy::same_functions_in_if_condition, + clippy::shadow_unrelated, + clippy::similar_names, + clippy::single_component_path_imports, + clippy::too_many_arguments, + clippy::too_many_lines, + clippy::type_complexity, + clippy::unused_self, + clippy::used_underscore_binding, +)] + extern crate dir; extern crate itertools; extern crate libc; @@ -92,7 +140,7 @@ impl From for Address { impl<'a> From<&'a json::H160> for Address { fn from(json: &'a json::H160) -> Self { - let mut a = [0u8; 20]; + let mut a = [0_u8; 20]; a.copy_from_slice(json); From::from(a) } diff --git a/accounts/ethstore/src/presale.rs b/accounts/ethstore/src/presale.rs index b317e8ca73b..9e36d4f6a5e 100644 --- a/accounts/ethstore/src/presale.rs +++ b/accounts/ethstore/src/presale.rs @@ -31,15 +31,15 @@ pub struct PresaleWallet { impl From for PresaleWallet { fn from(wallet: json::PresaleWallet) -> Self { - let mut iv = [0u8; 16]; + let mut iv = [0_u8; 16]; iv.copy_from_slice(&wallet.encseed[..16]); - let mut ciphertext = vec![]; + let mut ciphertext = Vec::new(); ciphertext.extend_from_slice(&wallet.encseed[16..]); - PresaleWallet { - iv: iv, - ciphertext: ciphertext, + Self { + iv, + ciphertext, address: Address::from(wallet.address), } } @@ -51,12 +51,12 @@ impl PresaleWallet { let file = fs::File::open(path)?; let presale = json::PresaleWallet::load(file) .map_err(|e| Error::InvalidKeyFile(format!("{}", e)))?; - Ok(PresaleWallet::from(presale)) + Ok(Self::from(presale)) } /// Decrypt the wallet. pub fn decrypt(&self, password: &Password) -> Result { - let mut derived_key = [0u8; 32]; + let mut derived_key = [0_u8; 32]; let salt = pbkdf2::Salt(password.as_bytes()); let sec = pbkdf2::Secret(password.as_bytes()); pbkdf2::sha256(2000, salt, sec, &mut derived_key); diff --git a/accounts/ethstore/src/random.rs b/accounts/ethstore/src/random.rs index 1faa5182465..3ec44bfc5fa 100644 --- a/accounts/ethstore/src/random.rs +++ b/accounts/ethstore/src/random.rs @@ -22,7 +22,7 @@ pub trait Random { impl Random for [u8; 16] { fn random() -> Self { - let mut result = [0u8; 16]; + let mut result = [0_u8; 16]; let mut rng = OsRng; rng.fill_bytes(&mut result); result @@ -31,7 +31,7 @@ impl Random for [u8; 16] { impl Random for [u8; 32] { fn random() -> Self { - let mut result = [0u8; 32]; + let mut result = [0_u8; 32]; let mut rng = OsRng; rng.fill_bytes(&mut result); result diff --git a/accounts/ethstore/src/secret_store.rs b/accounts/ethstore/src/secret_store.rs index 9632c345e9d..7879f812d82 100644 --- a/accounts/ethstore/src/secret_store.rs +++ b/accounts/ethstore/src/secret_store.rs @@ -43,7 +43,7 @@ pub struct StoreAccountRef { } impl PartialOrd for StoreAccountRef { - fn partial_cmp(&self, other: &StoreAccountRef) -> Option { + fn partial_cmp(&self, other: &Self) -> Option { Some(self.address.cmp(&other.address).then_with(|| self.vault.cmp(&other.vault))) } } @@ -148,24 +148,25 @@ pub trait SecretStore: SimpleSecretStore { impl StoreAccountRef { /// Create reference to root account with given address - pub fn root(address: Address) -> Self { - StoreAccountRef::new(SecretVaultRef::Root, address) + pub const fn root(address: Address) -> Self { + Self::new(SecretVaultRef::Root, address) } /// Create reference to vault account with given address pub fn vault(vault_name: &str, address: Address) -> Self { - StoreAccountRef::new(SecretVaultRef::Vault(vault_name.to_owned()), address) + Self::new(SecretVaultRef::Vault(vault_name.to_owned()), address) } /// Create new account reference - pub fn new(vault_ref: SecretVaultRef, address: Address) -> Self { - StoreAccountRef { - vault: vault_ref, - address: address, + pub const fn new(vault: SecretVaultRef, address: Address) -> Self { + Self { + vault, + address, } } } +#[allow(clippy::derive_hash_xor_eq)] impl Hash for StoreAccountRef { fn hash(&self, state: &mut H) { self.address.hash(state); diff --git a/accounts/ethstore/tests/api.rs b/accounts/ethstore/tests/api.rs index a5d39f346e6..1aca323befd 100644 --- a/accounts/ethstore/tests/api.rs +++ b/accounts/ethstore/tests/api.rs @@ -14,6 +14,54 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . +#![warn( + clippy::all, + clippy::pedantic, + clippy::nursery, +)] +#![allow( + clippy::blacklisted_name, + clippy::cast_lossless, + clippy::cast_possible_truncation, + clippy::cast_possible_wrap, + clippy::cast_precision_loss, + clippy::cast_ptr_alignment, + clippy::cast_sign_loss, + clippy::cognitive_complexity, + clippy::default_trait_access, + clippy::enum_glob_use, + clippy::eval_order_dependence, + clippy::fallible_impl_from, + clippy::float_cmp, + clippy::identity_op, + clippy::if_not_else, + clippy::indexing_slicing, + clippy::inline_always, + clippy::items_after_statements, + clippy::large_enum_variant, + clippy::many_single_char_names, + clippy::match_same_arms, + clippy::missing_errors_doc, + clippy::missing_safety_doc, + clippy::module_inception, + clippy::module_name_repetitions, + clippy::must_use_candidate, + clippy::needless_pass_by_value, + clippy::needless_update, + clippy::non_ascii_literal, + clippy::option_option, + clippy::pub_enum_variant_names, + clippy::same_functions_in_if_condition, + clippy::shadow_unrelated, + clippy::similar_names, + clippy::single_component_path_imports, + clippy::too_many_arguments, + clippy::too_many_lines, + clippy::type_complexity, + clippy::unused_self, + clippy::used_underscore_binding, +)] + extern crate rand; extern crate ethstore; extern crate ethereum_types; diff --git a/accounts/ethstore/tests/util/transient_dir.rs b/accounts/ethstore/tests/util/transient_dir.rs index 8bee9ae6def..c5b190774f6 100644 --- a/accounts/ethstore/tests/util/transient_dir.rs +++ b/accounts/ethstore/tests/util/transient_dir.rs @@ -35,9 +35,9 @@ pub struct TransientDir { impl TransientDir { pub fn create() -> Result { let path = random_dir(); - let result = TransientDir { + let result = Self { dir: RootDiskDirectory::create(&path)?, - path: path, + path, }; Ok(result) @@ -45,9 +45,9 @@ impl TransientDir { pub fn open() -> Self { let path = random_dir(); - TransientDir { + Self { dir: RootDiskDirectory::at(&path), - path: path, + path, } } } diff --git a/accounts/src/account_data.rs b/accounts/src/account_data.rs index cceb74bbcd2..4784331542f 100644 --- a/accounts/src/account_data.rs +++ b/accounts/src/account_data.rs @@ -24,7 +24,7 @@ use std::{ use parity_crypto::publickey::Address; use ethkey::Password; use serde_derive::{Serialize, Deserialize}; -use serde_json; + /// Type of unlock. #[derive(Clone, PartialEq)] @@ -57,14 +57,14 @@ pub struct AccountMeta { } impl AccountMeta { - /// Read a hash map of Address -> AccountMeta + /// Read a hash map of `Address` -> `AccountMeta` pub fn read(reader: R) -> Result, serde_json::Error> where R: ::std::io::Read, { serde_json::from_reader(reader) } - /// Write a hash map of Address -> AccountMeta + /// Write a hash map of `Address` -> `AccountMeta` pub fn write(m: &HashMap, writer: &mut W) -> Result<(), serde_json::Error> where W: ::std::io::Write, { diff --git a/accounts/src/error.rs b/accounts/src/error.rs index 1bbcf35ad49..1c3d354bafc 100644 --- a/accounts/src/error.rs +++ b/accounts/src/error.rs @@ -31,16 +31,16 @@ pub enum SignError { impl fmt::Display for SignError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - match *self { - SignError::NotUnlocked => write!(f, "Account is locked"), - SignError::NotFound => write!(f, "Account does not exist"), - SignError::SStore(ref e) => write!(f, "{}", e), + match self { + Self::NotUnlocked => write!(f, "Account is locked"), + Self::NotFound => write!(f, "Account does not exist"), + Self::SStore(e) => write!(f, "{}", e), } } } impl From for SignError { fn from(e: SSError) -> Self { - SignError::SStore(e) + Self::SStore(e) } } diff --git a/accounts/src/lib.rs b/accounts/src/lib.rs index 1e470b784f9..1c86d78123f 100644 --- a/accounts/src/lib.rs +++ b/accounts/src/lib.rs @@ -14,9 +14,57 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . +//! Account management. + #![warn(missing_docs)] -//! Account management. +#![warn( + clippy::all, + clippy::pedantic, + clippy::nursery, +)] +#![allow( + clippy::blacklisted_name, + clippy::cast_lossless, + clippy::cast_possible_truncation, + clippy::cast_possible_wrap, + clippy::cast_precision_loss, + clippy::cast_ptr_alignment, + clippy::cast_sign_loss, + clippy::cognitive_complexity, + clippy::default_trait_access, + clippy::enum_glob_use, + clippy::eval_order_dependence, + clippy::fallible_impl_from, + clippy::float_cmp, + clippy::identity_op, + clippy::if_not_else, + clippy::indexing_slicing, + clippy::inline_always, + clippy::items_after_statements, + clippy::large_enum_variant, + clippy::many_single_char_names, + clippy::match_same_arms, + clippy::missing_errors_doc, + clippy::missing_safety_doc, + clippy::module_inception, + clippy::module_name_repetitions, + clippy::must_use_candidate, + clippy::needless_pass_by_value, + clippy::needless_update, + clippy::non_ascii_literal, + clippy::option_option, + clippy::pub_enum_variant_names, + clippy::same_functions_in_if_condition, + clippy::shadow_unrelated, + clippy::similar_names, + clippy::single_component_path_imports, + clippy::too_many_arguments, + clippy::too_many_lines, + clippy::type_complexity, + clippy::unused_self, + clippy::used_underscore_binding, +)] mod account_data; mod error; @@ -94,7 +142,7 @@ impl AccountProvider { address_book.remove(*addr); } - AccountProvider { + Self { unlocked_secrets: RwLock::new(HashMap::new()), unlocked: RwLock::new(HashMap::new()), address_book: RwLock::new(address_book), @@ -107,14 +155,14 @@ impl AccountProvider { /// Creates not disk backed provider. pub fn transient_provider() -> Self { - AccountProvider { + Self { unlocked_secrets: RwLock::new(HashMap::new()), unlocked: RwLock::new(HashMap::new()), address_book: RwLock::new(AddressBook::transient()), sstore: Box::new(EthStore::open(Box::new(MemoryDirectory::default())).expect("MemoryDirectory load always succeeds; qed")), transient_sstore: transient_sstore(), unlock_keep_secret: false, - blacklisted_accounts: vec![], + blacklisted_accounts: Vec::new(), } } @@ -126,10 +174,10 @@ impl AccountProvider { /// Creates new random account and returns address and public key pub fn new_account_and_public(&self, password: &Password) -> Result<(Address, Public), Error> { let acc = Random.generate().expect("secp context has generation capabilities; qed"); - let public = acc.public().clone(); + let public = acc.public(); let secret = acc.secret().clone(); let account = self.sstore.insert_account(SecretVaultRef::Root, secret, password)?; - Ok((account.address, public)) + Ok((account.address, *public)) } /// Inserts new account into underlying store. @@ -138,7 +186,7 @@ impl AccountProvider { let account = self.sstore.insert_account(SecretVaultRef::Root, secret, password)?; if self.blacklisted_accounts.contains(&account.address) { self.sstore.remove_account(&account, password)?; - return Err(Error::InvalidAccount.into()); + return Err(Error::InvalidAccount); } Ok(account.address) } @@ -149,8 +197,8 @@ impl AccountProvider { pub fn derive_account(&self, address: &Address, password: Option, derivation: Derivation, save: bool) -> Result { - let account = self.sstore.account_ref(&address)?; - let password = password.map(Ok).unwrap_or_else(|| self.password(&account))?; + let account = self.sstore.account_ref(address)?; + let password = password.map_or_else(|| self.password(&account), Ok)?; Ok( if save { self.sstore.insert_derived(SecretVaultRef::Root, &account, &password, derivation)?.address } else { self.sstore.generate_derived(&account, &password, derivation)? } @@ -160,7 +208,7 @@ impl AccountProvider { /// Import a new presale wallet. pub fn import_presale(&self, presale_json: &[u8], password: &Password) -> Result { let account = self.sstore.import_presale(SecretVaultRef::Root, presale_json, password)?; - Ok(Address::from(account.address).into()) + Ok(account.address) } /// Import a new wallet. @@ -168,9 +216,9 @@ impl AccountProvider { let account = self.sstore.import_wallet(SecretVaultRef::Root, json, password, gen_id)?; if self.blacklisted_accounts.contains(&account.address) { self.sstore.remove_account(&account, password)?; - return Err(Error::InvalidAccount.into()); + return Err(Error::InvalidAccount); } - Ok(Address::from(account.address).into()) + Ok(account.address) } /// Checks whether an account with a given address is present. @@ -218,8 +266,7 @@ impl AccountProvider { pub fn accounts_info(&self) -> Result, Error> { let r = self.sstore.accounts()? .into_iter() - .filter(|a| !self.blacklisted_accounts.contains(&a.address)) - .map(|a| (a.address.clone(), self.account_meta(a.address).ok().unwrap_or_default())) + .filter_map(|a| if self.blacklisted_accounts.contains(&a.address) { None } else { Some((a.address, self.account_meta(a.address).ok().unwrap_or_default())) }) .collect(); Ok(r) } @@ -253,13 +300,13 @@ impl AccountProvider { /// Returns `true` if the password for `account` is `password`. `false` if not. pub fn test_password(&self, address: &Address, password: &Password) -> Result { - self.sstore.test_password(&self.sstore.account_ref(&address)?, password) + self.sstore.test_password(&self.sstore.account_ref(address)?, password) .map_err(Into::into) } /// Permanently removes an account. pub fn kill_account(&self, address: &Address, password: &Password) -> Result<(), Error> { - self.sstore.remove_account(&self.sstore.account_ref(&address)?, &password)?; + self.sstore.remove_account(&self.sstore.account_ref(address)?, password)?; Ok(()) } @@ -292,7 +339,7 @@ impl AccountProvider { } else { // verify password by signing dump message // result may be discarded - let _ = self.sstore.sign(&account, &password, &Default::default())?; + let _ = self.sstore.sign(&account, &password, &parity_crypto::publickey::Message::zero())?; } let data = AccountData { unlock, password }; @@ -307,8 +354,8 @@ impl AccountProvider { if let Unlock::OneTime = data.unlock { unlocked.remove(account).expect("data exists: so key must exist: qed"); } - if let Unlock::Timed(ref end) = data.unlock { - if Instant::now() > *end { + if let Unlock::Timed(end) = data.unlock { + if Instant::now() > end { unlocked.remove(account).expect("data exists: so key must exist: qed"); return Err(SignError::NotUnlocked); } @@ -351,14 +398,11 @@ impl AccountProvider { /// Signs the message. If password is not provided the account must be unlocked. pub fn sign(&self, address: Address, password: Option, message: Message) -> Result { let account = self.sstore.account_ref(&address)?; - match self.unlocked_secrets.read().get(&account) { - Some(secret) => { - Ok(self.sstore.sign_with_secret(&secret, &message)?) - }, - None => { - let password = password.map(Ok).unwrap_or_else(|| self.password(&account))?; - Ok(self.sstore.sign(&account, &password, &message)?) - } + if let Some(secret) = self.unlocked_secrets.read().get(&account) { + Ok(self.sstore.sign_with_secret(secret, &message)?) + } else { + let password = password.map_or_else(|| self.password(&account), Ok)?; + Ok(self.sstore.sign(&account, &password, &message)?) } } @@ -367,7 +411,7 @@ impl AccountProvider { -> Result { let account = self.sstore.account_ref(address)?; - let password = password.map(Ok).unwrap_or_else(|| self.password(&account))?; + let password = password.map_or_else(|| self.password(&account), Ok)?; Ok(self.sstore.sign_derived(&account, &password, derivation, &message)?) } @@ -418,20 +462,20 @@ impl AccountProvider { /// Decrypts a message. If password is not provided the account must be unlocked. pub fn decrypt(&self, address: Address, password: Option, shared_mac: &[u8], message: &[u8]) -> Result, SignError> { let account = self.sstore.account_ref(&address)?; - let password = password.map(Ok).unwrap_or_else(|| self.password(&account))?; + let password = password.map_or_else(|| self.password(&account), Ok)?; Ok(self.sstore.decrypt(&account, &password, shared_mac, message)?) } /// Agree on shared key. pub fn agree(&self, address: Address, password: Option, other_public: &Public) -> Result { let account = self.sstore.account_ref(&address)?; - let password = password.map(Ok).unwrap_or_else(|| self.password(&account))?; + let password = password.map_or_else(|| self.password(&account), Ok)?; Ok(self.sstore.agree(&account, &password, other_public)?) } /// Returns the underlying `SecretStore` reference if one exists. pub fn list_geth_accounts(&self, testnet: bool) -> Vec
{ - self.sstore.list_geth_accounts(testnet).into_iter().map(|a| Address::from(a).into()).collect() + self.sstore.list_geth_accounts(testnet).into_iter().collect() } /// Returns the underlying `SecretStore` reference if one exists. @@ -637,7 +681,7 @@ mod tests { ap.blacklisted_accounts = vec![acc]; // then - assert_eq!(ap.accounts_info().unwrap().keys().cloned().collect::>(), vec![]); - assert_eq!(ap.accounts().unwrap(), vec![]); + assert_eq!(ap.accounts_info().unwrap().keys().cloned().collect::>(), Vec::new()); + assert_eq!(ap.accounts().unwrap(), Vec::new()); } } diff --git a/accounts/src/stores.rs b/accounts/src/stores.rs index 1d1d0ea7135..dabcc7264e8 100644 --- a/accounts/src/stores.rs +++ b/accounts/src/stores.rs @@ -33,7 +33,7 @@ pub struct AddressBook { impl AddressBook { /// Creates new address book at given directory. pub fn new(path: &Path) -> Self { - let mut r = AddressBook { + let mut r = Self { cache: DiskMap::new(path, "address_book.json") }; r.cache.revert(AccountMeta::read); @@ -42,7 +42,7 @@ impl AddressBook { /// Creates transient address book (no changes are saved to disk). pub fn transient() -> Self { - AddressBook { + Self { cache: DiskMap::transient() } } @@ -60,7 +60,7 @@ impl AddressBook { pub fn set_name(&mut self, a: Address, name: String) { { let x = self.cache.entry(a) - .or_insert_with(|| AccountMeta {name: Default::default(), meta: "{}".to_owned(), uuid: None}); + .or_insert_with(|| AccountMeta { name: String::new(), meta: "{}".to_owned(), uuid: None }); x.name = name; } self.save(); @@ -70,7 +70,7 @@ impl AddressBook { pub fn set_meta(&mut self, a: Address, meta: String) { { let x = self.cache.entry(a) - .or_insert_with(|| AccountMeta {name: "Anonymous".to_owned(), meta: Default::default(), uuid: None}); + .or_insert_with(|| AccountMeta { name: "Anonymous".to_owned(), meta: String::new(), uuid: None }); x.meta = meta; } self.save(); @@ -83,7 +83,7 @@ impl AddressBook { } } -/// Disk-serializable HashMap +/// Disk-serializable hash map #[derive(Debug)] struct DiskMap { path: PathBuf, @@ -109,15 +109,15 @@ impl DiskMap { let mut path = path.to_owned(); path.push(file_name); trace!(target: "diskmap", "path={:?}", path); - DiskMap { - path: path, + Self { + path, cache: HashMap::new(), transient: false, } } pub fn transient() -> Self { - let mut map = DiskMap::new(&PathBuf::new(), "diskmap.json".into()); + let mut map = Self::new(&PathBuf::new(), "diskmap.json"); map.transient = true; map } @@ -178,7 +178,7 @@ mod tests { b.set_name(Address::from_low_u64_be(1), "One".to_owned()); b.set_name(Address::from_low_u64_be(2), "Two".to_owned()); b.set_name(Address::from_low_u64_be(3), "Three".to_owned()); - b.remove(Address::from_low_u64_be(2).into()); + b.remove(Address::from_low_u64_be(2)); let b = AddressBook::new(tempdir.path()); assert_eq!(b.get(), vec![