index: Ensure block locator is not stale after chain reorg.

This commit is contained in:
Jim Posen 2018-08-27 15:26:29 -07:00
parent 4368384f1d
commit 62b7a4f094
2 changed files with 30 additions and 0 deletions

View file

@ -113,6 +113,11 @@ void BaseIndex::ThreadSync()
Commit();
break;
}
if (pindex_next->pprev != pindex && !Rewind(pindex, pindex_next->pprev)) {
FatalError("%s: Failed to rewind index %s to a previous chain tip",
__func__, GetName());
return;
}
pindex = pindex_next;
}
@ -167,6 +172,22 @@ bool BaseIndex::CommitInternal(CDBBatch& batch)
return true;
}
bool BaseIndex::Rewind(const CBlockIndex* current_tip, const CBlockIndex* new_tip)
{
assert(current_tip == m_best_block_index);
assert(current_tip->GetAncestor(new_tip->nHeight) == new_tip);
// In the case of a reorg, ensure persisted block locator is not stale.
m_best_block_index = new_tip;
if (!Commit()) {
// If commit fails, revert the best block index to avoid corruption.
m_best_block_index = current_tip;
return false;
}
return true;
}
void BaseIndex::BlockConnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex,
const std::vector<CTransactionRef>& txn_conflicted)
{
@ -194,6 +215,11 @@ void BaseIndex::BlockConnected(const std::shared_ptr<const CBlock>& block, const
best_block_index->GetBlockHash().ToString());
return;
}
if (best_block_index != pindex->pprev && !Rewind(best_block_index, pindex->pprev)) {
FatalError("%s: Failed to rewind index %s to a previous chain tip",
__func__, GetName());
return;
}
}
if (WriteBlock(*block, pindex)) {

View file

@ -80,6 +80,10 @@ protected:
/// commit more index state.
virtual bool CommitInternal(CDBBatch& batch);
/// Rewind index to an earlier chain tip during a chain reorg. The tip must
/// be an ancestor of the current best block.
virtual bool Rewind(const CBlockIndex* current_tip, const CBlockIndex* new_tip);
virtual DB& GetDB() const = 0;
/// Get the name of the index for display in logs.