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

Handle failing case for update account cache in require #9989

Merged
merged 1 commit into from
Dec 3, 2018
Merged
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
31 changes: 15 additions & 16 deletions ethcore/src/state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -960,7 +960,7 @@ impl<B: Backend> State<B> {
#[cfg(feature="to-pod-full")]
/// Populate a PodAccount map from this state.
/// Warning this is not for real time use.
/// Use of this method requires FatDB mode to be able
/// Use of this method requires FatDB mode to be able
/// to iterate on accounts.
pub fn to_pod_full(&self) -> Result<PodState, Error> {

Expand All @@ -971,7 +971,7 @@ impl<B: Backend> State<B> {

let trie = self.factories.trie.readonly(self.db.as_hashdb(), &self.root)?;

// put trie in cache
// put trie in cache
for item in trie.iter()? {
if let Ok((addr, _dbval)) = item {
let address = Address::from_slice(&addr);
Expand Down Expand Up @@ -1194,7 +1194,7 @@ impl<B: Backend> State<B> {
self.note_cache(a);

// at this point the entry is guaranteed to be in the cache.
Ok(RefMut::map(self.cache.borrow_mut(), |c| {
let mut account = RefMut::map(self.cache.borrow_mut(), |c| {
let entry = c.get_mut(a).expect("entry known to exist in the cache; qed");

match &mut entry.account {
Expand All @@ -1204,20 +1204,19 @@ impl<B: Backend> State<B> {

// set the dirty flag after changing account data.
entry.state = AccountState::Dirty;
match entry.account {
Some(ref mut account) => {
if require_code {
let addr_hash = account.address_hash(a);
let accountdb = self.factories.accountdb.readonly(self.db.as_hashdb(), addr_hash);

// FIXME (Issue #9838): update_account_cache can fail in rare cases, but we cannot return error in RefMut wrapper.
Self::update_account_cache(RequireCache::Code, account, &self.db, accountdb.as_hashdb());
}
account
},
_ => panic!("Required account must always exist; qed"),
entry.account.as_mut().expect("Required account must always exist; qed")
});

if require_code {
let addr_hash = account.address_hash(a);
let accountdb = self.factories.accountdb.readonly(self.db.as_hashdb(), addr_hash);

if !Self::update_account_cache(RequireCache::Code, &mut account, &self.db, accountdb.as_hashdb()) {
return Err(Box::new(TrieError::IncompleteDatabase(H256::from(a))))
}
}))
}

Ok(account)
}

/// Replace account code and storage. Creates account if it does not exist.
Expand Down