Implement roll-back limit for reorganisation

Closes #713.
This commit is contained in:
Jack Grigg
2017-06-21 23:53:01 +12:00
parent e6850571dd
commit 57e6ecda5a
6 changed files with 120 additions and 2 deletions

View File

@@ -2631,6 +2631,31 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo
const CBlockIndex *pindexOldTip = chainActive.Tip();
const CBlockIndex *pindexFork = chainActive.FindFork(pindexMostWork);
// - On ChainDB initialization, pindexOldTip will be null, so there are no removable blocks.
// - If pindexMostWork is in a chain that doesn't have the same genesis block as our chain,
// then pindexFork will be null, and we would need to remove the entire chain including
// our genesis block. In practice this (probably) won't happen because of checks elsewhere.
auto reorgLength = pindexOldTip ? pindexOldTip->nHeight - (pindexFork ? pindexFork->nHeight : -1) : 0;
static_assert(MAX_REORG_LENGTH > 0, "We must be able to reorg some distance");
if (reorgLength > MAX_REORG_LENGTH) {
auto msg = strprintf(_(
"A block chain reorganization has been detected that would roll back %d blocks! "
"This is larger than the maximum of %d blocks, and so the node is shutting down for your safety."
), reorgLength, MAX_REORG_LENGTH) + "\n\n" +
_("Reorganization details") + ":\n" +
"- " + strprintf(_("Current tip: %s, height %d, work %s"),
pindexOldTip->phashBlock->GetHex(), pindexOldTip->nHeight, pindexOldTip->nChainWork.GetHex()) + "\n" +
"- " + strprintf(_("New tip: %s, height %d, work %s"),
pindexMostWork->phashBlock->GetHex(), pindexMostWork->nHeight, pindexMostWork->nChainWork.GetHex()) + "\n" +
"- " + strprintf(_("Fork point: %s, height %d"),
pindexFork->phashBlock->GetHex(), pindexFork->nHeight) + "\n\n" +
_("Please help, human!");
LogPrintf("*** %s\n", msg);
uiInterface.ThreadSafeMessageBox(msg, "", CClientUIInterface::MSG_ERROR);
StartShutdown();
return false;
}
// Disconnect active blocks which are no longer in the best chain.
while (chainActive.Tip() && chainActive.Tip() != pindexFork) {
if (!DisconnectTip(state))