Cache address hash (#1943)
This commit is contained in:
parent
eed3ef403a
commit
108024e98d
@ -16,11 +16,12 @@
|
|||||||
|
|
||||||
//! Single account in the system.
|
//! Single account in the system.
|
||||||
|
|
||||||
|
use std::collections::hash_map::Entry;
|
||||||
use util::*;
|
use util::*;
|
||||||
use pod_account::*;
|
use pod_account::*;
|
||||||
use account_db::*;
|
use account_db::*;
|
||||||
|
|
||||||
use std::cell::{Ref, RefCell};
|
use std::cell::{Ref, RefCell, Cell};
|
||||||
|
|
||||||
/// Single account in the system.
|
/// Single account in the system.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -39,6 +40,8 @@ pub struct Account {
|
|||||||
code_cache: Bytes,
|
code_cache: Bytes,
|
||||||
// Account is new or has been modified
|
// Account is new or has been modified
|
||||||
filth: Filth,
|
filth: Filth,
|
||||||
|
// Cached address hash.
|
||||||
|
address_hash: Cell<Option<H256>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Account {
|
impl Account {
|
||||||
@ -53,6 +56,7 @@ impl Account {
|
|||||||
code_hash: Some(code.sha3()),
|
code_hash: Some(code.sha3()),
|
||||||
code_cache: code,
|
code_cache: code,
|
||||||
filth: Filth::Dirty,
|
filth: Filth::Dirty,
|
||||||
|
address_hash: Cell::new(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,6 +70,7 @@ impl Account {
|
|||||||
code_hash: pod.code.as_ref().map(|c| c.sha3()),
|
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()),
|
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,
|
filth: Filth::Dirty,
|
||||||
|
address_hash: Cell::new(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,6 +84,7 @@ impl Account {
|
|||||||
code_hash: Some(SHA3_EMPTY),
|
code_hash: Some(SHA3_EMPTY),
|
||||||
code_cache: vec![],
|
code_cache: vec![],
|
||||||
filth: Filth::Dirty,
|
filth: Filth::Dirty,
|
||||||
|
address_hash: Cell::new(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,6 +99,7 @@ impl Account {
|
|||||||
code_hash: Some(r.val_at(3)),
|
code_hash: Some(r.val_at(3)),
|
||||||
code_cache: vec![],
|
code_cache: vec![],
|
||||||
filth: Filth::Clean,
|
filth: Filth::Clean,
|
||||||
|
address_hash: Cell::new(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,6 +114,7 @@ impl Account {
|
|||||||
code_hash: None,
|
code_hash: None,
|
||||||
code_cache: vec![],
|
code_cache: vec![],
|
||||||
filth: Filth::Dirty,
|
filth: Filth::Dirty,
|
||||||
|
address_hash: Cell::new(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,8 +134,17 @@ impl Account {
|
|||||||
|
|
||||||
/// Set (and cache) the contents of the trie's storage at `key` to `value`.
|
/// Set (and cache) the contents of the trie's storage at `key` to `value`.
|
||||||
pub fn set_storage(&mut self, key: H256, value: H256) {
|
pub fn set_storage(&mut self, key: H256, value: H256) {
|
||||||
self.storage_overlay.borrow_mut().insert(key, (Filth::Dirty, value));
|
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;
|
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`.
|
/// Get (and cache) the contents of the trie's storage at `key`.
|
||||||
@ -158,6 +175,16 @@ impl Account {
|
|||||||
self.code_hash.clone().unwrap_or(SHA3_EMPTY)
|
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 -
|
/// returns the account's code. If `None` then the code cache isn't available -
|
||||||
/// get someone who knows to call `note_code`.
|
/// get someone who knows to call `note_code`.
|
||||||
pub fn code(&self) -> Option<&[u8]> {
|
pub fn code(&self) -> Option<&[u8]> {
|
||||||
@ -233,17 +260,21 @@ impl Account {
|
|||||||
|
|
||||||
/// Increment the nonce of the account by one.
|
/// Increment the nonce of the account by one.
|
||||||
pub fn add_balance(&mut self, x: &U256) {
|
pub fn add_balance(&mut self, x: &U256) {
|
||||||
|
if !x.is_zero() {
|
||||||
self.balance = self.balance + *x;
|
self.balance = self.balance + *x;
|
||||||
self.filth = Filth::Dirty;
|
self.filth = Filth::Dirty;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Increment the nonce of the account by one.
|
/// Increment the nonce of the account by one.
|
||||||
/// Panics if balance is less than `x`
|
/// Panics if balance is less than `x`
|
||||||
pub fn sub_balance(&mut self, x: &U256) {
|
pub fn sub_balance(&mut self, x: &U256) {
|
||||||
|
if !x.is_zero() {
|
||||||
assert!(self.balance >= *x);
|
assert!(self.balance >= *x);
|
||||||
self.balance = self.balance - *x;
|
self.balance = self.balance - *x;
|
||||||
self.filth = Filth::Dirty;
|
self.filth = Filth::Dirty;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Commit the `storage_overlay` to the backing DB and update `storage_root`.
|
/// Commit the `storage_overlay` to the backing DB and update `storage_root`.
|
||||||
pub fn commit_storage(&mut self, trie_factory: &TrieFactory, db: &mut AccountDBMut) {
|
pub fn commit_storage(&mut self, trie_factory: &TrieFactory, db: &mut AccountDBMut) {
|
||||||
|
@ -181,7 +181,7 @@ impl State {
|
|||||||
/// Mutate storage of account `address` so that it is `value` for `key`.
|
/// Mutate storage of account `address` so that it is `value` for `key`.
|
||||||
pub fn storage_at(&self, address: &Address, key: &H256) -> H256 {
|
pub fn storage_at(&self, address: &Address, key: &H256) -> H256 {
|
||||||
self.ensure_cached(address, false,
|
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`.
|
/// Mutate storage of account `a` so that it is `value` for `key`.
|
||||||
@ -260,7 +260,7 @@ impl State {
|
|||||||
for (address, ref mut a) in accounts.iter_mut() {
|
for (address, ref mut a) in accounts.iter_mut() {
|
||||||
match a {
|
match a {
|
||||||
&mut&mut Some(ref mut account) if account.is_dirty() => {
|
&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_storage(trie_factory, &mut account_db);
|
||||||
account.commit_code(&mut account_db);
|
account.commit_code(&mut account_db);
|
||||||
}
|
}
|
||||||
@ -355,7 +355,8 @@ impl State {
|
|||||||
}
|
}
|
||||||
if require_code {
|
if require_code {
|
||||||
if let Some(ref mut account) = self.cache.borrow_mut().get_mut(a).unwrap().as_mut() {
|
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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -393,7 +394,8 @@ impl State {
|
|||||||
RefMut::map(self.cache.borrow_mut(), |c| {
|
RefMut::map(self.cache.borrow_mut(), |c| {
|
||||||
let account = c.get_mut(a).unwrap().as_mut().unwrap();
|
let account = c.get_mut(a).unwrap().as_mut().unwrap();
|
||||||
if require_code {
|
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
|
account
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user