Skip to content

Commit

Permalink
Handle failing case for update account cache in require (openethereum…
Browse files Browse the repository at this point in the history
  • Loading branch information
sorpaas authored and insipx committed Dec 17, 2018
1 parent e46e3ac commit 15a8b88
Showing 1 changed file with 15 additions and 16 deletions.
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

0 comments on commit 15a8b88

Please sign in to comment.