From b4b883b3418796b22380f89317c1637bc3561965 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Wed, 8 Jun 2016 17:17:37 +0400 Subject: [PATCH] keys import (#1240) * pattern importing * tests for import * cli options for account import * [options] for import also * removed globbing * removed glob crate refs --- parity/cli.rs | 4 +- parity/main.rs | 5 +++ util/res/pat/p1.json | 21 ++++++++++ util/res/pat/p2.json | 21 ++++++++++ util/src/keys/geth_import.rs | 75 ++++++++++++++++++++++++++++++++++-- util/src/keys/mod.rs | 1 + 6 files changed, 122 insertions(+), 5 deletions(-) create mode 100644 util/res/pat/p1.json create mode 100644 util/res/pat/p2.json diff --git a/parity/cli.rs b/parity/cli.rs index 0b3c96c55..b8aa88299 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -23,7 +23,8 @@ Parity. Ethereum Client. Usage: parity daemon [options] - parity account (new | list) [options] + parity account (new | list ) [options] + parity account import ... [options] parity import [ ] [options] parity export [ ] [options] parity signer new-token [options] @@ -212,6 +213,7 @@ pub struct Args { pub cmd_new_token: bool, pub arg_pid_file: String, pub arg_file: Option, + pub arg_path: Vec, pub flag_chain: String, pub flag_db_path: String, pub flag_identity: String, diff --git a/parity/main.rs b/parity/main.rs index 016b20117..58d5fe18e 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -482,6 +482,11 @@ fn execute_account_cli(conf: Configuration) { for &(addr, _) in &secret_store.accounts().unwrap() { println!("{:?}", addr); } + return; + } + if conf.args.cmd_import { + let imported = util::keys::import_keys_paths(&mut secret_store, &conf.args.arg_path).unwrap(); + println!("Imported {} keys", imported); } } diff --git a/util/res/pat/p1.json b/util/res/pat/p1.json new file mode 100644 index 000000000..afc376774 --- /dev/null +++ b/util/res/pat/p1.json @@ -0,0 +1,21 @@ +{ + "address": "3f49624084b67849c7b4e805c5988c21a430f9d9", + "Crypto": { + "cipher": "aes-128-ctr", + "ciphertext": "9f27e3dd4fc73e7103ed61e5493662189a3eb52223ae49e3d1deacc04c889eae", + "cipherparams": { + "iv": "457494bf05f2618c397dc74dbb5181c0" + }, + "kdf": "scrypt", + "kdfparams": { + "dklen": 32, + "n": 262144, + "p": 1, + "r": 8, + "salt": "db14edb18c41ee7f5ec4397df89c3a2ae4d0af60884c52bb54ce490574f8df33" + }, + "mac": "572d24532438d31fdf513c744a3ff26c933ffda5744ee42bc71661cbe3f2112e" + }, + "id": "62a0ad73-556d-496a-8e1c-0783d30d3ace", + "version": 3 +} diff --git a/util/res/pat/p2.json b/util/res/pat/p2.json new file mode 100644 index 000000000..b14922037 --- /dev/null +++ b/util/res/pat/p2.json @@ -0,0 +1,21 @@ +{ + "address": "5ba4dcf897e97c2bdf8315b9ef26c13c085988cf", + "Crypto": { + "cipher": "aes-128-ctr", + "ciphertext": "d4a08ec930163778273920f6ad1d49b71836337be6fd9863993ac700a612fddd", + "cipherparams": { + "iv": "89ce5ec129fc27cd5bcbeb8c92bdad50" + }, + "kdf": "scrypt", + "kdfparams": { + "dklen": 32, + "n": 262144, + "p": 1, + "r": 8, + "salt": "612ab108dc37e69ee8af37a7b24bf7f2234086d7bbf945bacdeccce331f7f84a" + }, + "mac": "4152caa7444e06784223d735cea80cd2690b4c587ad8db3d5529442227b25695" + }, + "id": "35086353-fb12-4029-b56b-033cd61ce35b", + "version": 3 +} diff --git a/util/src/keys/geth_import.rs b/util/src/keys/geth_import.rs index a72c570fa..509ebc89f 100644 --- a/util/src/keys/geth_import.rs +++ b/util/src/keys/geth_import.rs @@ -80,9 +80,10 @@ pub fn import_geth_key(secret_store: &mut SecretStore, geth_keyfile_path: &Path) } /// Imports all geth keys in the directory -pub fn import_geth_keys(secret_store: &mut SecretStore, geth_keyfiles_directory: &Path) -> Result<(), ImportError> { +pub fn import_geth_keys(secret_store: &mut SecretStore, geth_keyfiles_directory: &Path) -> Result { use std::path::PathBuf; let geth_files = try!(enumerate_geth_keys(geth_keyfiles_directory)); + let mut total = 0; for &(ref address, ref file_path) in &geth_files { let mut path = PathBuf::new(); path.push(geth_keyfiles_directory); @@ -90,18 +91,45 @@ pub fn import_geth_keys(secret_store: &mut SecretStore, geth_keyfiles_directory: if let Err(e) = import_geth_key(secret_store, Path::new(&path)) { warn!("Skipped geth address {}, error importing: {:?}", address, e) } + else { total = total + 1} } - Ok(()) + Ok(total) } /// Gets the default geth keystore directory. -/// -/// Based on https://github.com/ethereum/go-ethereum/blob/e553215/common/path.go#L75 pub fn keystore_dir(is_testnet: bool) -> PathBuf { path::ethereum::with_default(if is_testnet {"testnet/keystore"} else {"keystore"}) } +/// Imports key(s) from provided file/directory +pub fn import_keys_path(secret_store: &mut SecretStore, path: &str) -> Result { + // check if it is just one file or directory + if let Ok(meta) = fs::metadata(path) { + if meta.is_file() { + try!(import_geth_key(secret_store, Path::new(path))); + return Ok(1); + } + else if meta.is_dir() { + return Ok(try!(fs::read_dir(path)).fold( + 0, + |total, p| + total + + match p { + Ok(dir_entry) => import_keys_path(secret_store, dir_entry.path().to_str().unwrap()).unwrap_or_else(|_| 0), + Err(e) => { warn!("Error importing dir entry: {:?}", e); 0 }, + } + )) + } + } + Ok(0) +} + +/// Imports all keys from list of provided files/directories +pub fn import_keys_paths(secret_store: &mut SecretStore, path: &[String]) -> Result { + Ok(path.iter().fold(0, |total, ref p| total + import_keys_path(secret_store, &p).unwrap_or_else(|_| 0))) +} + #[cfg(test)] mod tests { use super::*; @@ -115,10 +143,21 @@ mod tests { } } + fn pat_path() -> &'static str { + match ::std::fs::metadata("res") { + Ok(_) => "res/pat", + Err(_) => "util/res/pat" + } + } + fn test_path_param(param_val: &'static str) -> String { test_path().to_owned() + param_val } + fn pat_path_param(param_val: &'static str) -> String { + pat_path().to_owned() + param_val + } + #[test] fn can_enumerate() { let keys = enumerate_geth_keys(Path::new(test_path())).unwrap(); @@ -191,4 +230,32 @@ mod tests { assert!(val.is_ok()); assert_eq!(32, val.unwrap().len()); } + + #[test] + fn can_import_by_filename() { + let temp = ::devtools::RandomTempPath::create_dir(); + let mut secret_store = SecretStore::new_in(temp.as_path()); + + let amount = import_keys_path(&mut secret_store, &pat_path_param("/p1.json")).unwrap(); + assert_eq!(1, amount); + } + + #[test] + fn can_import_by_dir() { + let temp = ::devtools::RandomTempPath::create_dir(); + let mut secret_store = SecretStore::new_in(temp.as_path()); + + let amount = import_keys_path(&mut secret_store, pat_path()).unwrap(); + assert_eq!(2, amount); + } + + #[test] + fn can_import_mulitple() { + let temp = ::devtools::RandomTempPath::create_dir(); + let mut secret_store = SecretStore::new_in(temp.as_path()); + + let amount = import_keys_paths(&mut secret_store, &[pat_path_param("/p1.json"), pat_path_param("/p2.json")]).unwrap(); + assert_eq!(2, amount); + } + } diff --git a/util/src/keys/mod.rs b/util/src/keys/mod.rs index 38fa51eca..39c39aeef 100644 --- a/util/src/keys/mod.rs +++ b/util/src/keys/mod.rs @@ -23,3 +23,4 @@ mod test_account_provider; pub use self::store::AccountProvider; pub use self::test_account_provider::{TestAccount, TestAccountProvider}; +pub use self::geth_import::import_keys_paths;