Name and meta in accounts (#1695)

* Introduce persistent name() and meta() in SecretStore.

* Quick stash.

* Fix build.

* Add ethcore_set methods.

* Bug fixes for default values.

* Move to personal to ensure set API exposed.

* Add UUID to accounts info.

* Add tests.
This commit is contained in:
Gav Wood
2016-07-24 17:38:21 +02:00
committed by GitHub
parent a76981a61d
commit 3f841cc578
10 changed files with 281 additions and 35 deletions

View File

@@ -16,6 +16,7 @@
//! Account management (personal) rpc implementation
use std::sync::{Arc, Weak};
use std::collections::{BTreeMap};
use jsonrpc_core::*;
use v1::traits::Personal;
use v1::types::{H160 as RpcH160, TransactionRequest};
@@ -104,4 +105,39 @@ impl<C: 'static, M: 'static> Personal for PersonalClient<C, M> where C: MiningBl
unlock_sign_and_dispatch(&*take_weak!(self.client), &*take_weak!(self.miner), request, &*accounts, sender, password)
})
}
fn set_account_name(&self, params: Params) -> Result<Value, Error> {
try!(self.active());
let store = take_weak!(self.accounts);
from_params::<(RpcH160, _)>(params).and_then(|(addr, name)| {
let addr: Address = addr.into();
store.set_account_name(addr, name).map_err(|_| Error::invalid_params()).map(|_| Value::Null)
})
}
fn set_account_meta(&self, params: Params) -> Result<Value, Error> {
try!(self.active());
let store = take_weak!(self.accounts);
from_params::<(RpcH160, _)>(params).and_then(|(addr, meta)| {
let addr: Address = addr.into();
store.set_account_meta(addr, meta).map_err(|_| Error::invalid_params()).map(|_| Value::Null)
})
}
fn accounts_info(&self, _: Params) -> Result<Value, Error> {
try!(self.active());
let store = take_weak!(self.accounts);
Ok(Value::Object(try!(store.accounts_info().map_err(|_| Error::invalid_params())).into_iter().map(|(a, v)| {
let m = map![
"name".to_owned() => to_value(&v.name).unwrap(),
"meta".to_owned() => to_value(&v.meta).unwrap(),
"uuid".to_owned() => if let &Some(ref uuid) = &v.uuid {
to_value(uuid).unwrap()
} else {
Value::Null
}
];
(format!("0x{}", a.hex()), Value::Object(m))
}).collect::<BTreeMap<_, _>>()))
}
}

View File

@@ -118,6 +118,66 @@ fn new_account() {
assert_eq!(res, Some(response));
}
#[test]
fn should_be_able_to_get_account_info() {
let tester = setup(None);
tester.accounts.new_account("").unwrap();
let accounts = tester.accounts.accounts();
assert_eq!(accounts.len(), 1);
let address = accounts[0];
let uuid = tester.accounts.accounts_info().unwrap().get(&address).unwrap().uuid.as_ref().unwrap().clone();
tester.accounts.set_account_name(address.clone(), "Test".to_owned()).unwrap();
tester.accounts.set_account_meta(address.clone(), "{foo: 69}".to_owned()).unwrap();
let request = r#"{"jsonrpc": "2.0", "method": "personal_accountsInfo", "params": [], "id": 1}"#;
let res = tester.io.handle_request(request);
let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":{{\"0x{}\":{{\"meta\":\"{{foo: 69}}\",\"name\":\"Test\",\"uuid\":\"{}\"}}}},\"id\":1}}", address.hex(), uuid);
assert_eq!(res, Some(response));
}
#[test]
fn should_be_able_to_set_name() {
let tester = setup(None);
tester.accounts.new_account("").unwrap();
let accounts = tester.accounts.accounts();
assert_eq!(accounts.len(), 1);
let address = accounts[0];
let request = format!(r#"{{"jsonrpc": "2.0", "method": "personal_setAccountName", "params": ["0x{}", "Test"], "id": 1}}"#, address.hex());
let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#;
let res = tester.io.handle_request(&request);
assert_eq!(res, Some(response.into()));
let uuid = tester.accounts.accounts_info().unwrap().get(&address).unwrap().uuid.as_ref().unwrap().clone();
let request = r#"{"jsonrpc": "2.0", "method": "personal_accountsInfo", "params": [], "id": 1}"#;
let res = tester.io.handle_request(request);
let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":{{\"0x{}\":{{\"meta\":\"{{}}\",\"name\":\"Test\",\"uuid\":\"{}\"}}}},\"id\":1}}", address.hex(), uuid);
assert_eq!(res, Some(response));
}
#[test]
fn should_be_able_to_set_meta() {
let tester = setup(None);
tester.accounts.new_account("").unwrap();
let accounts = tester.accounts.accounts();
assert_eq!(accounts.len(), 1);
let address = accounts[0];
let request = format!(r#"{{"jsonrpc": "2.0", "method": "personal_setAccountMeta", "params": ["0x{}", "{{foo: 69}}"], "id": 1}}"#, address.hex());
let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#;
let res = tester.io.handle_request(&request);
assert_eq!(res, Some(response.into()));
let uuid = tester.accounts.accounts_info().unwrap().get(&address).unwrap().uuid.as_ref().unwrap().clone();
let request = r#"{"jsonrpc": "2.0", "method": "personal_accountsInfo", "params": [], "id": 1}"#;
let res = tester.io.handle_request(request);
let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":{{\"0x{}\":{{\"meta\":\"{{foo: 69}}\",\"name\":\"{}\",\"uuid\":\"{}\"}}}},\"id\":1}}", address.hex(), uuid, uuid);
assert_eq!(res, Some(response));
}
#[test]
fn sign_and_send_transaction_with_invalid_password() {
let tester = setup(None);

View File

@@ -36,6 +36,15 @@ pub trait Personal: Sized + Send + Sync + 'static {
/// Returns `true` if Trusted Signer is enabled, `false` otherwise.
fn signer_enabled(&self, _: Params) -> Result<Value, Error>;
/// Set an account's name.
fn set_account_name(&self, _: Params) -> Result<Value, Error>;
/// Set an account's metadata string.
fn set_account_meta(&self, _: Params) -> Result<Value, Error>;
/// Returns accounts information.
fn accounts_info(&self, _: Params) -> Result<Value, Error>;
/// Should be used to convert object to io delegate.
fn to_delegate(self) -> IoDelegate<Self> {
let mut delegate = IoDelegate::new(Arc::new(self));
@@ -44,6 +53,10 @@ pub trait Personal: Sized + Send + Sync + 'static {
delegate.add_method("personal_newAccount", Personal::new_account);
delegate.add_method("personal_unlockAccount", Personal::unlock_account);
delegate.add_method("personal_signAndSendTransaction", Personal::sign_and_send_transaction);
delegate.add_method("personal_setAccountName", Personal::set_account_name);
delegate.add_method("personal_setAccountMeta", Personal::set_account_meta);
delegate.add_method("personal_accountsInfo", Personal::accounts_info);
delegate
}
}