diff options
| author | Jim Posen <[email protected]> | 2018-08-27 15:26:29 -0700 |
|---|---|---|
| committer | Jim Posen <[email protected]> | 2019-04-06 12:03:21 -0700 |
| commit | 62b7a4f09409f60a35fc99ddb70f9199ac511a53 (patch) | |
| tree | d1dcd104c38707ebb15efd1dcf2c7cc6bbc1cb39 /src/index | |
| parent | index: Allow atomic commits of index state to be extended. (diff) | |
| download | discoin-62b7a4f09409f60a35fc99ddb70f9199ac511a53.tar.xz discoin-62b7a4f09409f60a35fc99ddb70f9199ac511a53.zip | |
index: Ensure block locator is not stale after chain reorg.
Diffstat (limited to 'src/index')
| -rw-r--r-- | src/index/base.cpp | 26 | ||||
| -rw-r--r-- | src/index/base.h | 4 |
2 files changed, 30 insertions, 0 deletions
diff --git a/src/index/base.cpp b/src/index/base.cpp index 15ad04d46..9e48f0bd2 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 77e614a3a..31acbed0c 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. |