Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Minor optimizations #1943

Merged
merged 1 commit into from
Aug 18, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 39 additions & 8 deletions ethcore/src/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@

//! Single account in the system.

use std::collections::hash_map::Entry;
use util::*;
use pod_account::*;
use account_db::*;

use std::cell::{Ref, RefCell};
use std::cell::{Ref, RefCell, Cell};

/// Single account in the system.
#[derive(Clone)]
Expand All @@ -39,6 +40,8 @@ pub struct Account {
code_cache: Bytes,
// Account is new or has been modified
filth: Filth,
// Cached address hash.
address_hash: Cell<Option<H256>>,
}

impl Account {
Expand All @@ -53,6 +56,7 @@ impl Account {
code_hash: Some(code.sha3()),
code_cache: code,
filth: Filth::Dirty,
address_hash: Cell::new(None),
}
}

Expand All @@ -66,6 +70,7 @@ impl Account {
code_hash: pod.code.as_ref().map(|c| c.sha3()),
code_cache: pod.code.as_ref().map_or_else(|| { warn!("POD account with unknown code is being created! Assuming no code."); vec![] }, |c| c.clone()),
filth: Filth::Dirty,
address_hash: Cell::new(None),
}
}

Expand All @@ -79,6 +84,7 @@ impl Account {
code_hash: Some(SHA3_EMPTY),
code_cache: vec![],
filth: Filth::Dirty,
address_hash: Cell::new(None),
}
}

Expand All @@ -93,6 +99,7 @@ impl Account {
code_hash: Some(r.val_at(3)),
code_cache: vec![],
filth: Filth::Clean,
address_hash: Cell::new(None),
}
}

Expand All @@ -107,6 +114,7 @@ impl Account {
code_hash: None,
code_cache: vec![],
filth: Filth::Dirty,
address_hash: Cell::new(None),
}
}

Expand All @@ -126,8 +134,17 @@ impl Account {

/// Set (and cache) the contents of the trie's storage at `key` to `value`.
pub fn set_storage(&mut self, key: H256, value: H256) {
self.storage_overlay.borrow_mut().insert(key, (Filth::Dirty, value));
self.filth = Filth::Dirty;
match self.storage_overlay.borrow_mut().entry(key) {
Entry::Occupied(ref mut entry) if entry.get().1 != value => {
entry.insert((Filth::Dirty, value));
self.filth = Filth::Dirty;
},
Entry::Vacant(entry) => {
entry.insert((Filth::Dirty, value));
self.filth = Filth::Dirty;
},
_ => (),
}
}

/// Get (and cache) the contents of the trie's storage at `key`.
Expand Down Expand Up @@ -158,6 +175,16 @@ impl Account {
self.code_hash.clone().unwrap_or(SHA3_EMPTY)
}

/// return the code hash associated with this account.
pub fn address_hash(&self, address: &Address) -> H256 {
let hash = self.address_hash.get();
hash.unwrap_or_else(|| {
let hash = address.sha3();
self.address_hash.set(Some(hash.clone()));
hash
})
}

/// returns the account's code. If `None` then the code cache isn't available -
/// get someone who knows to call `note_code`.
pub fn code(&self) -> Option<&[u8]> {
Expand Down Expand Up @@ -233,16 +260,20 @@ impl Account {

/// Increment the nonce of the account by one.
pub fn add_balance(&mut self, x: &U256) {
self.balance = self.balance + *x;
self.filth = Filth::Dirty;
if !x.is_zero() {
self.balance = self.balance + *x;
self.filth = Filth::Dirty;
}
}

/// Increment the nonce of the account by one.
/// Panics if balance is less than `x`
pub fn sub_balance(&mut self, x: &U256) {
assert!(self.balance >= *x);
self.balance = self.balance - *x;
self.filth = Filth::Dirty;
if !x.is_zero() {
assert!(self.balance >= *x);
self.balance = self.balance - *x;
self.filth = Filth::Dirty;
}
}

/// Commit the `storage_overlay` to the backing DB and update `storage_root`.
Expand Down
10 changes: 6 additions & 4 deletions ethcore/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ impl State {
/// Mutate storage of account `address` so that it is `value` for `key`.
pub fn storage_at(&self, address: &Address, key: &H256) -> H256 {
self.ensure_cached(address, false,
|a| a.as_ref().map_or(H256::new(), |a|a.storage_at(&AccountDB::new(self.db.as_hashdb(), address), key)))
|a| a.as_ref().map_or(H256::new(), |a|a.storage_at(&AccountDB::from_hash(self.db.as_hashdb(), a.address_hash(address)), key)))
}

/// Mutate storage of account `a` so that it is `value` for `key`.
Expand Down Expand Up @@ -260,7 +260,7 @@ impl State {
for (address, ref mut a) in accounts.iter_mut() {
match a {
&mut&mut Some(ref mut account) if account.is_dirty() => {
let mut account_db = AccountDBMut::new(db, address);
let mut account_db = AccountDBMut::from_hash(db, account.address_hash(address));
account.commit_storage(trie_factory, &mut account_db);
account.commit_code(&mut account_db);
}
Expand Down Expand Up @@ -355,7 +355,8 @@ impl State {
}
if require_code {
if let Some(ref mut account) = self.cache.borrow_mut().get_mut(a).unwrap().as_mut() {
account.cache_code(&AccountDB::new(self.db.as_hashdb(), a));
let addr_hash = account.address_hash(a);
account.cache_code(&AccountDB::from_hash(self.db.as_hashdb(), addr_hash));
}
}

Expand Down Expand Up @@ -393,7 +394,8 @@ impl State {
RefMut::map(self.cache.borrow_mut(), |c| {
let account = c.get_mut(a).unwrap().as_mut().unwrap();
if require_code {
account.cache_code(&AccountDB::new(self.db.as_hashdb(), a));
let addr_hash = account.address_hash(a);
account.cache_code(&AccountDB::from_hash(self.db.as_hashdb(), addr_hash));
}
account
})
Expand Down