Auto merge of #2463 - str4d:713-rollback-limit, r=str4d
Implement roll-back limit for reorganisation Part of #2905. Closes #713.
This commit is contained in:
45
src/main.cpp
45
src/main.cpp
@@ -2761,6 +2761,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.
|
||||
bool fBlocksDisconnected = false;
|
||||
while (chainActive.Tip() && chainActive.Tip() != pindexFork) {
|
||||
@@ -3952,6 +3977,26 @@ bool RewindBlockIndex(const CChainParams& params)
|
||||
}
|
||||
|
||||
// nHeight is now the height of the first insufficiently-validated block, or tipheight + 1
|
||||
auto rewindLength = chainActive.Height() - nHeight;
|
||||
if (rewindLength > 0 && rewindLength > MAX_REORG_LENGTH) {
|
||||
auto pindexOldTip = chainActive.Tip();
|
||||
auto pindexRewind = chainActive[nHeight - 1];
|
||||
auto msg = strprintf(_(
|
||||
"A block chain rewind 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."
|
||||
), rewindLength, MAX_REORG_LENGTH) + "\n\n" +
|
||||
_("Rewind details") + ":\n" +
|
||||
"- " + strprintf(_("Current tip: %s, height %d"),
|
||||
pindexOldTip->phashBlock->GetHex(), pindexOldTip->nHeight) + "\n" +
|
||||
"- " + strprintf(_("Rewinding to: %s, height %d"),
|
||||
pindexRewind->phashBlock->GetHex(), pindexRewind->nHeight) + "\n\n" +
|
||||
_("Please help, human!");
|
||||
LogPrintf("*** %s\n", msg);
|
||||
uiInterface.ThreadSafeMessageBox(msg, "", CClientUIInterface::MSG_ERROR);
|
||||
StartShutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
CValidationState state;
|
||||
CBlockIndex* pindex = chainActive.Tip();
|
||||
while (chainActive.Height() >= nHeight) {
|
||||
|
||||
Reference in New Issue
Block a user