secret store separated from util (#1304)

* bump rust-crypto

* initial version of account provider utilizing secret store

* update lazy_static to latest version

* AccountProvider accounts method

* new AccountProvider tests in progress

* basic tests for new AccountProvider

* ethcore compiles with new account provider and secret store

* ethcore-rpc build now compiling with new AccountProvider

* most rpc tests passing with new accounts_provider

* fixed basic_authority tests

* fixed eth_transaction_count rpc test

* fixed mocked/eth.rs tests

* fixed personal tests

* fixed personal signer rpc tests

* removed warnings

* parity compiling fine with new sstore

* fixed import direction

* do not unlock temporarily when we have the password

* removed TODO in account import

* display warning on auto account import failure

* fixed compiling of ethstore on windows

* ethstore as a part of parity repo

* added ethkey
This commit is contained in:
Marek Kotewicz
2016-06-20 00:10:34 +02:00
committed by Gav Wood
parent 08522eec37
commit 6b074e8fb2
84 changed files with 4027 additions and 2682 deletions

109
ethstore/src/dir/disk.rs Normal file
View File

@@ -0,0 +1,109 @@
use std::{fs, ffi, io};
use std::path::{PathBuf, Path};
use std::collections::HashMap;
use ethkey::Address;
use {libc, json, SafeAccount, Error};
use super::KeyDirectory;
#[cfg(not(windows))]
fn restrict_permissions_to_owner(file_path: &Path) -> Result<(), i32> {
let cstr = ffi::CString::new(file_path.to_str().unwrap()).unwrap();
match unsafe { libc::chmod(cstr.as_ptr(), libc::S_IWUSR | libc::S_IRUSR) } {
0 => Ok(()),
x => Err(x),
}
}
#[cfg(windows)]
fn restrict_permissions_to_owner(file_path: &Path) -> Result<(), i32> {
Ok(())
}
pub struct DiskDirectory {
path: PathBuf,
}
impl DiskDirectory {
pub fn create<P>(path: P) -> Result<Self, Error> where P: AsRef<Path> {
try!(fs::create_dir_all(&path));
Ok(Self::at(path))
}
pub fn at<P>(path: P) -> Self where P: AsRef<Path> {
DiskDirectory {
path: path.as_ref().to_path_buf(),
}
}
/// all accounts found in keys directory
fn files(&self) -> Result<HashMap<PathBuf, SafeAccount>, Error> {
// it's not done using one iterator cause
// there is an issue with rustc and it takes tooo much time to compile
let paths = try!(fs::read_dir(&self.path))
.flat_map(Result::ok)
.filter(|entry| {
let metadata = entry.metadata();
metadata.is_ok() && !metadata.unwrap().is_dir()
})
.map(|entry| entry.path())
.collect::<Vec<PathBuf>>();
let files: Result<Vec<_>, _> = paths.iter()
.map(fs::File::open)
.collect();
let files = try!(files);
let accounts = files.into_iter()
.map(json::KeyFile::load)
.zip(paths.into_iter())
.filter_map(|(file, path)| file.ok().map(|file| (path, SafeAccount::from(file))))
.collect();
Ok(accounts)
}
}
impl KeyDirectory for DiskDirectory {
fn load(&self) -> Result<Vec<SafeAccount>, Error> {
let accounts = try!(self.files())
.into_iter()
.map(|(_, account)| account)
.collect();
Ok(accounts)
}
fn insert(&self, account: SafeAccount) -> Result<(), Error> {
// transform account into key file
let keyfile: json::KeyFile = account.into();
// build file path
let mut keyfile_path = self.path.clone();
keyfile_path.push(format!("{}", keyfile.id));
// save the file
let mut file = try!(fs::File::create(&keyfile_path));
try!(keyfile.write(&mut file).map_err(|e| Error::Custom(format!("{:?}", e))));
if let Err(_) = restrict_permissions_to_owner(&keyfile_path) {
fs::remove_file(&keyfile_path).expect("Expected to remove recently created file");
return Err(Error::Io(io::Error::last_os_error()));
}
Ok(())
}
fn remove(&self, address: &Address) -> Result<(), Error> {
// enumerate all entries in keystore
// and find entry with given address
let to_remove = try!(self.files())
.into_iter()
.find(|&(_, ref account)| &account.address == address);
// remove it
match to_remove {
None => Err(Error::InvalidAccount),
Some((path, _)) => fs::remove_file(path).map_err(From::from)
}
}
}

79
ethstore/src/dir/geth.rs Normal file
View File

@@ -0,0 +1,79 @@
use std::env;
use std::path::PathBuf;
use ethkey::Address;
use {SafeAccount, Error};
use super::{KeyDirectory, DiskDirectory, DirectoryType};
#[cfg(target_os = "macos")]
fn geth_dir_path() -> PathBuf {
let mut home = env::home_dir().expect("Failed to get home dir");
home.push("Library");
home.push("Ethereum");
home
}
#[cfg(windows)]
/// Default path for ethereum installation on Windows
pub fn geth_dir_path() -> PathBuf {
let mut home = env::home_dir().expect("Failed to get home dir");
home.push("AppData");
home.push("Roaming");
home.push("Ethereum");
home
}
#[cfg(not(any(target_os = "macos", windows)))]
/// Default path for ethereum installation on posix system which is not Mac OS
pub fn geth_dir_path() -> PathBuf {
let mut home = env::home_dir().expect("Failed to get home dir");
home.push(".ethereum");
home
}
fn geth_keystore(t: DirectoryType) -> PathBuf {
let mut dir = geth_dir_path();
match t {
DirectoryType::Testnet => {
dir.push("testnet");
dir.push("keystore");
},
DirectoryType::Main => {
dir.push("keystore");
}
}
dir
}
pub struct GethDirectory {
dir: DiskDirectory,
}
impl GethDirectory {
pub fn create(t: DirectoryType) -> Result<Self, Error> {
let result = GethDirectory {
dir: try!(DiskDirectory::create(geth_keystore(t))),
};
Ok(result)
}
pub fn open(t: DirectoryType) -> Self {
GethDirectory {
dir: DiskDirectory::at(geth_keystore(t)),
}
}
}
impl KeyDirectory for GethDirectory {
fn load(&self) -> Result<Vec<SafeAccount>, Error> {
self.dir.load()
}
fn insert(&self, account: SafeAccount) -> Result<(), Error> {
self.dir.insert(account)
}
fn remove(&self, address: &Address) -> Result<(), Error> {
self.dir.remove(address)
}
}

21
ethstore/src/dir/mod.rs Normal file
View File

@@ -0,0 +1,21 @@
use ethkey::Address;
use {SafeAccount, Error};
mod disk;
mod geth;
mod parity;
pub enum DirectoryType {
Testnet,
Main,
}
pub trait KeyDirectory: Send + Sync {
fn load(&self) -> Result<Vec<SafeAccount>, Error>;
fn insert(&self, account: SafeAccount) -> Result<(), Error>;
fn remove(&self, address: &Address) -> Result<(), Error>;
}
pub use self::disk::DiskDirectory;
pub use self::geth::GethDirectory;
pub use self::parity::ParityDirectory;

View File

@@ -0,0 +1,58 @@
use std::env;
use std::path::PathBuf;
use ethkey::Address;
use {SafeAccount, Error};
use super::{KeyDirectory, DiskDirectory, DirectoryType};
fn parity_dir_path() -> PathBuf {
let mut home = env::home_dir().expect("Failed to get home dir");
home.push(".parity");
home
}
fn parity_keystore(t: DirectoryType) -> PathBuf {
let mut dir = parity_dir_path();
match t {
DirectoryType::Testnet => {
dir.push("testnet_keys");
},
DirectoryType::Main => {
dir.push("keys");
}
}
dir
}
pub struct ParityDirectory {
dir: DiskDirectory,
}
impl ParityDirectory {
pub fn create(t: DirectoryType) -> Result<Self, Error> {
let result = ParityDirectory {
dir: try!(DiskDirectory::create(parity_keystore(t))),
};
Ok(result)
}
pub fn open(t: DirectoryType) -> Self {
ParityDirectory {
dir: DiskDirectory::at(parity_keystore(t)),
}
}
}
impl KeyDirectory for ParityDirectory {
fn load(&self) -> Result<Vec<SafeAccount>, Error> {
self.dir.load()
}
fn insert(&self, account: SafeAccount) -> Result<(), Error> {
self.dir.insert(account)
}
fn remove(&self, address: &Address) -> Result<(), Error> {
self.dir.remove(address)
}
}