diff --git a/ethstore/src/dir/mod.rs b/ethstore/src/dir/mod.rs index fb22c06ee..b6e168f6e 100755 --- a/ethstore/src/dir/mod.rs +++ b/ethstore/src/dir/mod.rs @@ -90,7 +90,7 @@ pub trait VaultKeyDirectory: KeyDirectory { fn set_meta(&self, meta: &str) -> Result<(), Error>; } -pub use self::disk::RootDiskDirectory; +pub use self::disk::{RootDiskDirectory, DiskKeyFileManager, KeyFileManager}; pub use self::memory::MemoryDirectory; pub use self::vault::VaultDiskDirectory; diff --git a/ethstore/src/import.rs b/ethstore/src/import.rs index b7497c9ff..2b2c34eb1 100644 --- a/ethstore/src/import.rs +++ b/ethstore/src/import.rs @@ -15,10 +15,29 @@ // along with Parity. If not, see . use std::collections::HashSet; +use std::path::Path; +use std::fs; + use ethkey::Address; -use dir::{paths, KeyDirectory, RootDiskDirectory}; +use dir::{paths, KeyDirectory, RootDiskDirectory, DiskKeyFileManager, KeyFileManager}; use Error; +/// Import an account from a file. +pub fn import_account(path: &Path, dst: &KeyDirectory) -> Result { + let key_manager = DiskKeyFileManager; + 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 account = fs::File::open(&path) + .map_err(Into::into) + .and_then(|file| key_manager.read(filename, file))?; + + let address = account.address.clone(); + if !existing_accounts.contains(&address) { + dst.insert(account)?; + } + Ok(address) +} + /// Import all accounts from one directory to the other. pub fn import_accounts(src: &KeyDirectory, dst: &KeyDirectory) -> Result, Error> { let accounts = src.load()?; diff --git a/ethstore/src/lib.rs b/ethstore/src/lib.rs index 145a58023..00a06a3e5 100755 --- a/ethstore/src/lib.rs +++ b/ethstore/src/lib.rs @@ -57,7 +57,7 @@ mod secret_store; pub use self::account::{SafeAccount, Crypto}; pub use self::error::Error; pub use self::ethstore::{EthStore, EthMultiStore}; -pub use self::import::{import_accounts, read_geth_accounts}; +pub use self::import::{import_account, import_accounts, read_geth_accounts}; pub use self::json::OpaqueKeyFile as KeyFile; pub use self::presale::PresaleWallet; pub use self::secret_store::{ diff --git a/parity/account.rs b/parity/account.rs index 2f177adf1..3b2fd3c2d 100644 --- a/parity/account.rs +++ b/parity/account.rs @@ -15,7 +15,7 @@ // along with Parity. If not, see . use std::path::PathBuf; -use ethcore::ethstore::{EthStore, SecretStore, import_accounts, read_geth_accounts}; +use ethcore::ethstore::{EthStore, SecretStore, import_account, import_accounts, read_geth_accounts}; use ethcore::ethstore::dir::RootDiskDirectory; use ethcore::ethstore::SecretVaultRef; use ethcore::account_provider::{AccountProvider, AccountProviderSettings}; @@ -51,10 +51,10 @@ pub struct ImportAccounts { pub spec: SpecType, } -/// Parameters for geth accounts' import +/// Parameters for geth accounts' import #[derive(Debug, PartialEq)] pub struct ImportFromGethAccounts { - /// import mainnet (false) or testnet (true) accounts + /// import mainnet (false) or testnet (true) accounts pub testnet: bool, /// directory to import accounts to pub to: String, @@ -94,16 +94,16 @@ fn new(n: NewAccount) -> Result { let secret_store = Box::new(secret_store(dir, Some(n.iterations))?); let acc_provider = AccountProvider::new(secret_store, AccountProviderSettings::default()); let new_account = acc_provider.new_account(&password).map_err(|e| format!("Could not create new account: {}", e))?; - Ok(format!("{:?}", new_account)) + Ok(format!("0x{:?}", new_account)) } fn list(list_cmd: ListAccounts) -> Result { let dir = Box::new(keys_dir(list_cmd.path, list_cmd.spec)?); let secret_store = Box::new(secret_store(dir, None)?); let acc_provider = AccountProvider::new(secret_store, AccountProviderSettings::default()); - let accounts = acc_provider.accounts(); + let accounts = acc_provider.accounts().map_err(|e| format!("{}", e))?; let result = accounts.into_iter() - .map(|a| format!("{:?}", a)) + .map(|a| format!("0x{:?}", a)) .collect::>() .join("\n"); @@ -113,10 +113,18 @@ fn list(list_cmd: ListAccounts) -> Result { fn import(i: ImportAccounts) -> Result { let to = keys_dir(i.to, i.spec)?; let mut imported = 0; + for path in &i.from { - let from = RootDiskDirectory::at(path); - imported += import_accounts(&from, &to).map_err(|_| "Importing accounts failed.")?.len(); + let path = PathBuf::from(path); + if path.is_dir() { + let from = RootDiskDirectory::at(&path); + imported += import_accounts(&from, &to).map_err(|e| format!("Importing accounts from {:?} failed: {}", path, e))?.len(); + } else if path.is_file() { + import_account(&path, &to).map_err(|e| format!("Importing account from {:?} failed: {}", path, e))?; + imported += 1; + } } + Ok(format!("{} account(s) imported", imported)) }