aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/index/base.cpp26
-rw-r--r--src/index/base.h4
2 files changed, 30 insertions, 0 deletions
diff --git a/src/index/base.cpp b/src/index/base.cpp
index 15ad04d462..9e48f0bd27 100644
--- a/src/index/base.cpp
+++ b/src/index/base.cpp
@@ -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)) {
diff --git a/src/index/base.h b/src/index/base.h
index 77e614a3af..31acbed0c1 100644
--- a/src/index/base.h
+++ b/src/index/base.h
@@ -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.