From 60691d03e0cbc9391fa215ee7119e233539b786b Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Mon, 3 Dec 2018 23:26:39 +0800 Subject: [PATCH] Handle failing case for update account cache in require (#9989) --- ethcore/src/state/mod.rs | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/ethcore/src/state/mod.rs b/ethcore/src/state/mod.rs index e6a96a0e8..b2c52e583 100644 --- a/ethcore/src/state/mod.rs +++ b/ethcore/src/state/mod.rs @@ -960,7 +960,7 @@ impl State { #[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 { @@ -971,7 +971,7 @@ impl State { 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); @@ -1194,7 +1194,7 @@ impl State { 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 { @@ -1204,20 +1204,19 @@ impl State { // 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); + entry.account.as_mut().expect("Required account must always exist; qed") + }); - // 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"), + 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.