refactoring to AccountService

This commit is contained in:
Nikolay Volf 2016-03-10 23:09:45 +04:00
parent 47aacbb819
commit a2dea3885b
3 changed files with 56 additions and 25 deletions

View File

@ -196,7 +196,7 @@ fn setup_log(init: &Option<String>) {
} }
#[cfg(feature = "rpc")] #[cfg(feature = "rpc")]
fn setup_rpc_server(client: Arc<Client>, sync: Arc<EthSync>, secret_store: Arc<SecretStore>, url: &str, cors_domain: &str, apis: Vec<&str>) -> Option<Arc<PanicHandler>> { fn setup_rpc_server(client: Arc<Client>, sync: Arc<EthSync>, secret_store: Arc<AccountService>, url: &str, cors_domain: &str, apis: Vec<&str>) -> Option<Arc<PanicHandler>> {
use rpc::v1::*; use rpc::v1::*;
let server = rpc::RpcServer::new(); let server = rpc::RpcServer::new();
@ -416,11 +416,7 @@ impl Configuration {
let sync = EthSync::register(service.network(), sync_config, client); let sync = EthSync::register(service.network(), sync_config, client);
// Secret Store // Secret Store
let secret_store = Arc::new(SecretStore::new()); let account_service = Arc::new(AccountService::new());
{
let import_ref = Arc::make_mut(&mut secret_store);
import_ref.try_import_existing();
}
// Setup rpc // Setup rpc
if self.args.flag_jsonrpc || self.args.flag_rpc { if self.args.flag_jsonrpc || self.args.flag_rpc {
@ -432,7 +428,7 @@ impl Configuration {
let cors = self.args.flag_rpccorsdomain.as_ref().unwrap_or(&self.args.flag_jsonrpc_cors); let cors = self.args.flag_rpccorsdomain.as_ref().unwrap_or(&self.args.flag_jsonrpc_cors);
// TODO: use this as the API list. // TODO: use this as the API list.
let apis = self.args.flag_rpcapi.as_ref().unwrap_or(&self.args.flag_jsonrpc_apis); let apis = self.args.flag_rpcapi.as_ref().unwrap_or(&self.args.flag_jsonrpc_apis);
let server_handler = setup_rpc_server(service.client(), sync.clone(), secret_store.clone(), &url, cors, apis.split(",").collect()); let server_handler = setup_rpc_server(service.client(), sync.clone(), account_service.clone(), &url, cors, apis.split(",").collect());
if let Some(handler) = server_handler { if let Some(handler) = server_handler {
panic_handler.forward_from(handler.deref()); panic_handler.forward_from(handler.deref());
} }

View File

@ -20,30 +20,28 @@ use jsonrpc_core::*;
use v1::traits::Personal; use v1::traits::Personal;
use util::keys::store::*; use util::keys::store::*;
use util::Address; use util::Address;
use std::sync::RwLock;
/// Account management (personal) rpc implementation. /// Account management (personal) rpc implementation.
pub struct PersonalClient { pub struct PersonalClient {
secret_store: Weak<RwLock<SecretStore>>, accounts: Weak<AccountProvider>,
} }
impl PersonalClient { impl PersonalClient {
/// Creates new PersonalClient /// Creates new PersonalClient
pub fn new(store: &Arc<RwLock<SecretStore>>) -> Self { pub fn new(store: &Arc<AccountProvider>) -> Self {
PersonalClient { PersonalClient {
secret_store: Arc::downgrade(store), accounts: Arc::downgrade(store),
} }
} }
} }
impl Personal for PersonalClient { impl Personal for PersonalClient {
fn accounts(&self, _: Params) -> Result<Value, Error> { fn accounts(&self, _: Params) -> Result<Value, Error> {
let store_wk = take_weak!(self.secret_store); let store = take_weak!(self.accounts);
let store = store_wk.read().unwrap();
match store.accounts() { match store.accounts() {
Ok(account_list) => { Ok(account_list) => {
Ok(Value::Array(account_list.iter() Ok(Value::Array(account_list.iter()
.map(|&(account, _)| Value::String(format!("{:?}", account))) .map(|&account| Value::String(format!("{:?}", account)))
.collect::<Vec<Value>>()) .collect::<Vec<Value>>())
) )
} }
@ -54,8 +52,7 @@ impl Personal for PersonalClient {
fn new_account(&self, params: Params) -> Result<Value, Error> { fn new_account(&self, params: Params) -> Result<Value, Error> {
from_params::<(String, )>(params).and_then( from_params::<(String, )>(params).and_then(
|(pass, )| { |(pass, )| {
let store_wk = take_weak!(self.secret_store); let store = take_weak!(self.accounts);
let mut store = store_wk.write().unwrap();
match store.new_account(&pass) { match store.new_account(&pass) {
Ok(address) => Ok(Value::String(format!("{:?}", address))), Ok(address) => Ok(Value::String(format!("{:?}", address))),
Err(_) => Err(Error::internal_error()) Err(_) => Err(Error::internal_error())
@ -67,8 +64,7 @@ impl Personal for PersonalClient {
fn unlock_account(&self, params: Params) -> Result<Value, Error> { fn unlock_account(&self, params: Params) -> Result<Value, Error> {
from_params::<(Address, String, u64)>(params).and_then( from_params::<(Address, String, u64)>(params).and_then(
|(account, account_pass, _)|{ |(account, account_pass, _)|{
let store_wk = take_weak!(self.secret_store); let store = take_weak!(self.accounts);
let store = store_wk.read().unwrap();
match store.unlock_account(&account, &account_pass) { match store.unlock_account(&account, &account_pass) {
Ok(_) => Ok(Value::Bool(true)), Ok(_) => Ok(Value::Bool(true)),
Err(_) => Ok(Value::Bool(false)), Err(_) => Ok(Value::Bool(false)),

View File

@ -80,16 +80,57 @@ struct AccountUnlock {
/// Basic account management trait /// Basic account management trait
pub trait AccountProvider : Send + Sync { pub trait AccountProvider : Send + Sync {
/// Lists all accounts
fn accounts(&self) -> Result<Vec<Address>, ::std::io::Error>;
/// Unlocks account with the password provided /// Unlocks account with the password provided
fn unlock_account(&self, account: &Address, pass: &str) -> Result<(), EncryptedHashMapError>; fn unlock_account(&self, account: &Address, pass: &str) -> Result<(), EncryptedHashMapError>;
/// Creates account /// Creates account
fn new_account(&mut self, pass: &str) -> Result<Address, ::std::io::Error>; fn new_account(&self, pass: &str) -> Result<Address, ::std::io::Error>;
/// Returns secret for unlocked account /// Returns secret for unlocked account
fn account_secret(&self, account: &Address) -> Result<crypto::Secret, SigningError>; fn account_secret(&self, account: &Address) -> Result<crypto::Secret, SigningError>;
/// Returns secret for unlocked account /// Returns secret for unlocked account
fn sign(&self, account: &Address, message: &H256) -> Result<crypto::Signature, SigningError>; fn sign(&self, account: &Address, message: &H256) -> Result<crypto::Signature, SigningError>;
} }
/// Thread-safe accounts management
pub struct AccountService {
secret_store: RwLock<SecretStore>,
}
impl AccountProvider for AccountService {
/// Lists all accounts
fn accounts(&self) -> Result<Vec<Address>, ::std::io::Error> {
Ok(try!(self.secret_store.read().unwrap().accounts()).iter().map(|&(addr, _)| addr).collect::<Vec<Address>>())
}
/// Unlocks account with the password provided
fn unlock_account(&self, account: &Address, pass: &str) -> Result<(), EncryptedHashMapError> {
self.secret_store.read().unwrap().unlock_account(account, pass)
}
/// Creates account
fn new_account(&self, pass: &str) -> Result<Address, ::std::io::Error> {
self.secret_store.write().unwrap().new_account(pass)
}
/// Returns secret for unlocked account
fn account_secret(&self, account: &Address) -> Result<crypto::Secret, SigningError> {
self.secret_store.read().unwrap().account_secret(account)
}
/// Returns secret for unlocked account
fn sign(&self, account: &Address, message: &H256) -> Result<crypto::Signature, SigningError> {
self.secret_store.read().unwrap().sign(account, message)
}
}
impl AccountService {
/// New account service with the default location
pub fn new() -> AccountService {
let secret_store = RwLock::new(SecretStore::new());
secret_store.write().unwrap().try_import_existing();
AccountService {
secret_store: secret_store
}
}
}
impl SecretStore { impl SecretStore {
/// new instance of Secret Store in default home directory /// new instance of Secret Store in default home directory
pub fn new() -> SecretStore { pub fn new() -> SecretStore {
@ -156,11 +197,9 @@ impl SecretStore {
unlocks: RwLock::new(HashMap::new()), unlocks: RwLock::new(HashMap::new()),
} }
} }
}
impl AccountProvider for SecretStore {
/// Unlocks account for use /// Unlocks account for use
fn unlock_account(&self, account: &Address, pass: &str) -> Result<(), EncryptedHashMapError> { pub fn unlock_account(&self, account: &Address, pass: &str) -> Result<(), EncryptedHashMapError> {
let secret_id = try!(self.account(&account).ok_or(EncryptedHashMapError::UnknownIdentifier)); let secret_id = try!(self.account(&account).ok_or(EncryptedHashMapError::UnknownIdentifier));
let secret = try!(self.get(&secret_id, pass)); let secret = try!(self.get(&secret_id, pass));
{ {
@ -174,7 +213,7 @@ impl AccountProvider for SecretStore {
} }
/// Creates new account /// Creates new account
fn new_account(&mut self, pass: &str) -> Result<Address, ::std::io::Error> { pub fn new_account(&mut self, pass: &str) -> Result<Address, ::std::io::Error> {
let secret = H256::random(); let secret = H256::random();
let key_id = H128::random(); let key_id = H128::random();
self.insert(key_id.clone(), secret, pass); self.insert(key_id.clone(), secret, pass);
@ -187,7 +226,7 @@ impl AccountProvider for SecretStore {
} }
/// Signs message with unlocked account /// Signs message with unlocked account
fn sign(&self, account: &Address, message: &H256) -> Result<crypto::Signature, SigningError> { pub fn sign(&self, account: &Address, message: &H256) -> Result<crypto::Signature, SigningError> {
let read_lock = self.unlocks.read().unwrap(); let read_lock = self.unlocks.read().unwrap();
let unlock = try!(read_lock.get(account).ok_or(SigningError::AccountNotUnlocked)); let unlock = try!(read_lock.get(account).ok_or(SigningError::AccountNotUnlocked));
match crypto::KeyPair::from_secret(unlock.secret) { match crypto::KeyPair::from_secret(unlock.secret) {
@ -200,7 +239,7 @@ impl AccountProvider for SecretStore {
} }
/// Returns secret for unlocked account /// Returns secret for unlocked account
fn account_secret(&self, account: &Address) -> Result<crypto::Secret, SigningError> { pub fn account_secret(&self, account: &Address) -> Result<crypto::Secret, SigningError> {
let read_lock = self.unlocks.read().unwrap(); let read_lock = self.unlocks.read().unwrap();
let unlock = try!(read_lock.get(account).ok_or(SigningError::AccountNotUnlocked)); let unlock = try!(read_lock.get(account).ok_or(SigningError::AccountNotUnlocked));
Ok(unlock.secret as crypto::Secret) Ok(unlock.secret as crypto::Secret)