Don't sync on top of pruned blocks (#2079)

* Don't sync to pruned blocks

* Typo

Co-Authored-By: arkpar <arkady.paronyan@gmail.com>
This commit is contained in:
Arkadiy Paronyan
2019-03-22 16:27:50 +01:00
committed by GitHub
parent 53f40c583d
commit 704d2a49c7
5 changed files with 59 additions and 21 deletions
+4
View File
@@ -142,6 +142,10 @@ pub trait Backend<Block, H>: AuxStore + Send + Sync where
fn blockchain(&self) -> &Self::Blockchain;
/// Returns reference to changes trie storage.
fn changes_trie_storage(&self) -> Option<&Self::ChangesTrieStorage>;
/// Returns true if state for given block is available.
fn have_state_at(&self, hash: &Block::Hash, _number: NumberFor<Block>) -> bool {
self.state_at(BlockId::Hash(hash.clone())).is_ok()
}
/// Returns state backend with post-state of given block.
fn state_at(&self, block: BlockId<Block>) -> error::Result<Self::State>;
/// Destroy state and save any useful data, such as cache.
+25 -11
View File
@@ -167,8 +167,10 @@ pub struct ClientInfo<Block: BlockT> {
pub enum BlockStatus {
/// Added to the import queue.
Queued,
/// Already in the blockchain.
InChain,
/// Already in the blockchain and the state is available.
InChainWithState,
/// In the blockchain, but the state is not available.
InChainPruned,
/// Block or parent is known to be bad.
KnownBad,
/// Not in the queue or the blockchain.
@@ -1073,9 +1075,19 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
return Ok(BlockStatus::Queued);
}
}
match self.backend.blockchain().header(*id).map_err(|e| error::Error::from_blockchain(Box::new(e)))?.is_some() {
true => Ok(BlockStatus::InChain),
false => Ok(BlockStatus::Unknown),
let hash_and_number = match id.clone() {
BlockId::Hash(hash) => self.backend.blockchain().number(hash)?.map(|n| (hash, n)),
BlockId::Number(n) => self.backend.blockchain().hash(n)?.map(|hash| (hash, n)),
};
match hash_and_number {
Some((hash, number)) => {
if self.backend().have_state_at(&hash, number) {
Ok(BlockStatus::InChainWithState)
} else {
Ok(BlockStatus::InChainPruned)
}
}
None => Ok(BlockStatus::Unknown),
}
}
@@ -1386,18 +1398,20 @@ impl<B, E, Block, RA> consensus::BlockImport<Block> for Client<B, E, Block, RA>
hash: Block::Hash,
parent_hash: Block::Hash,
) -> Result<ImportResult, Self::Error> {
match self.backend.blockchain().status(BlockId::Hash(parent_hash))
match self.block_status(&BlockId::Hash(parent_hash))
.map_err(|e| ConsensusError::from(ConsensusErrorKind::ClientImport(e.to_string())))?
{
blockchain::BlockStatus::InChain => {},
blockchain::BlockStatus::Unknown => return Ok(ImportResult::UnknownParent),
BlockStatus::InChainWithState | BlockStatus::Queued => {},
BlockStatus::Unknown | BlockStatus::InChainPruned => return Ok(ImportResult::UnknownParent),
BlockStatus::KnownBad => return Ok(ImportResult::KnownBad),
}
match self.backend.blockchain().status(BlockId::Hash(hash))
match self.block_status(&BlockId::Hash(hash))
.map_err(|e| ConsensusError::from(ConsensusErrorKind::ClientImport(e.to_string())))?
{
blockchain::BlockStatus::InChain => return Ok(ImportResult::AlreadyInChain),
blockchain::BlockStatus::Unknown => {},
BlockStatus::InChainWithState | BlockStatus::Queued => return Ok(ImportResult::AlreadyInChain),
BlockStatus::Unknown | BlockStatus::InChainPruned => {},
BlockStatus::KnownBad => return Ok(ImportResult::KnownBad),
}
Ok(ImportResult::imported())
@@ -109,7 +109,7 @@ impl<S, F, Block> BlockchainHeaderBackend<Block> for Blockchain<S, F> where Bloc
};
// if the header is from future or genesis (we never prune genesis) => return
if number.is_zero() || self.storage.status(BlockId::Number(number))? != BlockStatus::InChain {
if number.is_zero() || self.storage.status(BlockId::Number(number))? == BlockStatus::Unknown {
return Ok(None);
}