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

@@ -130,6 +130,27 @@ pub struct AccountProvider {
sstore: Box<SecretStore>,
}
/// Collected account metadata
#[derive(Clone, Debug, PartialEq)]
pub struct AccountMeta {
/// The name of the account.
pub name: String,
/// The rest of the metadata of the account.
pub meta: String,
/// The 128-bit UUID of the account, if it has one (brain-wallets don't).
pub uuid: Option<String>,
}
impl Default for AccountMeta {
fn default() -> Self {
AccountMeta {
name: String::new(),
meta: "{}".to_owned(),
uuid: None,
}
}
}
impl AccountProvider {
/// Creates new account provider.
pub fn new(sstore: Box<SecretStore>) -> Self {
@@ -167,6 +188,39 @@ impl AccountProvider {
self.sstore.accounts().into_iter().map(|a| H160(a.into())).collect()
}
/// Returns each account along with name and meta.
pub fn accounts_info(&self) -> Result<HashMap<H160, AccountMeta>, Error> {
let r: HashMap<H160, AccountMeta> = self.sstore.accounts()
.into_iter()
.map(|a| (H160(a.clone().into()), self.account_meta(a).unwrap_or(Default::default())))
.collect();
Ok(r)
}
/// Returns each account along with name and meta.
pub fn account_meta<A>(&self, account: A) -> Result<AccountMeta, Error> where Address: From<A> {
let account = Address::from(account).into();
Ok(AccountMeta {
name: try!(self.sstore.name(&account)),
meta: try!(self.sstore.meta(&account)),
uuid: self.sstore.uuid(&account).ok().map(Into::into), // allowed to not have a UUID
})
}
/// Returns each account along with name and meta.
pub fn set_account_name<A>(&self, account: A, name: String) -> Result<(), Error> where Address: From<A> {
let account = Address::from(account).into();
try!(self.sstore.set_name(&account, name));
Ok(())
}
/// Returns each account along with name and meta.
pub fn set_account_meta<A>(&self, account: A, meta: String) -> Result<(), Error> where Address: From<A> {
let account = Address::from(account).into();
try!(self.sstore.set_meta(&account, meta));
Ok(())
}
/// Helper method used for unlocking accounts.
fn unlock_account<A>(&self, account: A, password: String, unlock: Unlock) -> Result<(), Error> where Address: From<A> {
let a = Address::from(account);

View File

@@ -259,38 +259,35 @@ impl<'a> Executive<'a> {
let trace_info = tracer.prepare_trace_call(&params);
let cost = self.engine.cost_of_builtin(&params.code_address, data);
match cost <= params.gas {
true => {
self.engine.execute_builtin(&params.code_address, data, &mut output);
self.state.clear_snapshot();
if cost <= params.gas {
self.engine.execute_builtin(&params.code_address, data, &mut output);
self.state.clear_snapshot();
// trace only top level calls to builtins to avoid DDoS attacks
if self.depth == 0 {
let mut trace_output = tracer.prepare_trace_output();
if let Some(mut out) = trace_output.as_mut() {
*out = output.to_owned();
}
tracer.trace_call(
trace_info,
cost,
trace_output,
self.depth,
vec![],
delegate_call
);
// trace only top level calls to builtins to avoid DDoS attacks
if self.depth == 0 {
let mut trace_output = tracer.prepare_trace_output();
if let Some(mut out) = trace_output.as_mut() {
*out = output.to_owned();
}
Ok(params.gas - cost)
},
// just drain the whole gas
false => {
self.state.revert_snapshot();
tracer.trace_failed_call(trace_info, self.depth, vec![], delegate_call);
Err(evm::Error::OutOfGas)
tracer.trace_call(
trace_info,
cost,
trace_output,
self.depth,
vec![],
delegate_call
);
}
Ok(params.gas - cost)
} else {
// just drain the whole gas
self.state.revert_snapshot();
tracer.trace_failed_call(trace_info, self.depth, vec![], delegate_call);
Err(evm::Error::OutOfGas)
}
} else {
let trace_info = tracer.prepare_trace_call(&params);
@@ -304,7 +301,7 @@ impl<'a> Executive<'a> {
let mut unconfirmed_substate = Substate::new();
// TODO: make ActionParams pass by ref then avoid copy altogether.
let mut subvmtracer = vm_tracer.prepare_subtrace(params.code.as_ref().expect("scope is protected by params.code.is_some condition"));
let mut subvmtracer = vm_tracer.prepare_subtrace(params.code.as_ref().expect("scope is conditional on params.code.is_some(); qed"));
let res = {
self.exec_vm(params, &mut unconfirmed_substate, OutputPolicy::Return(output, trace_output.as_mut()), &mut subtracer, &mut subvmtracer)