diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 97f8dd5a4..6f44dd5bb 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -371,9 +371,27 @@ impl Client where V: Verifier { return Some(self.state()) } - self.block_header(id).map(|header| { + let block_number = match self.block_number(id.clone()) { + Some(num) => num, + None => return None, + }; + + self.block_header(id).and_then(|header| { let db = self.state_db.lock().unwrap().boxed_clone(); - State::from_existing(db, HeaderView::new(&header).state_root(), self.engine.account_start_nonce()) + + // early exit for pruned blocks + if db.is_pruned() && self.chain.best_block_number() >= block_number + HISTORY { + return None; + } + + let root = HeaderView::new(&header).state_root(); + + // TODO [rob]: refactor State::from_existing so we avoid doing redundant lookups. + if !db.contains(&root) { + return None; + } + + Some(State::from_existing(db, root, self.engine.account_start_nonce())) }) } diff --git a/util/src/journaldb/archivedb.rs b/util/src/journaldb/archivedb.rs index b554db885..c6acc1280 100644 --- a/util/src/journaldb/archivedb.rs +++ b/util/src/journaldb/archivedb.rs @@ -175,6 +175,8 @@ impl JournalDB for ArchiveDB { fn state(&self, id: &H256) -> Option { self.backing.get_by_prefix(&id.bytes()[0..12]).and_then(|b| Some(b.to_vec())) } + + fn is_pruned(&self) -> bool { false } } #[cfg(test)] diff --git a/util/src/journaldb/traits.rs b/util/src/journaldb/traits.rs index 10212f976..74149b062 100644 --- a/util/src/journaldb/traits.rs +++ b/util/src/journaldb/traits.rs @@ -42,4 +42,7 @@ pub trait JournalDB : HashDB + Send + Sync { fn state(&self, _id: &H256) -> Option { None } + + /// Whether this database is pruned. + fn is_pruned(&self) -> bool { true } } diff --git a/util/src/trie/triedb.rs b/util/src/trie/triedb.rs index 06076d273..1c6d2236b 100644 --- a/util/src/trie/triedb.rs +++ b/util/src/trie/triedb.rs @@ -59,7 +59,7 @@ impl<'db> TrieDB<'db> { /// Create a new trie with the backing database `db` and `root` /// Panics, if `root` does not exist pub fn new(db: &'db HashDB, root: &'db H256) -> Self { - if !db.exists(root) { + if !db.contains(root) { flushln!("TrieDB::new({}): Trie root not found!", root); panic!("Trie root not found!"); }