Auto merge of #3443 - daira:testnet-rollback, r=str4d

Support testnet rollback.

Part of #1302. Closes #2905.
This commit is contained in:
Homu 2018-08-08 05:28:08 -07:00
commit 40f320e0ee
3 changed files with 48 additions and 21 deletions

View File

@ -1434,6 +1434,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
LogPrintf("* Using %.1fMiB for chain state database\n", nCoinDBCache * (1.0 / 1024 / 1024)); LogPrintf("* Using %.1fMiB for chain state database\n", nCoinDBCache * (1.0 / 1024 / 1024));
LogPrintf("* Using %.1fMiB for in-memory UTXO set\n", nCoinCacheUsage * (1.0 / 1024 / 1024)); LogPrintf("* Using %.1fMiB for in-memory UTXO set\n", nCoinCacheUsage * (1.0 / 1024 / 1024));
bool clearWitnessCaches = false;
bool fLoaded = false; bool fLoaded = false;
while (!fLoaded) { while (!fLoaded) {
bool fReset = fReindex; bool fReset = fReindex;
@ -1493,7 +1495,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
if (!fReindex) { if (!fReindex) {
uiInterface.InitMessage(_("Rewinding blocks if needed...")); uiInterface.InitMessage(_("Rewinding blocks if needed..."));
if (!RewindBlockIndex(chainparams)) { if (!RewindBlockIndex(chainparams, clearWitnessCaches)) {
strLoadError = _("Unable to rewind the database to a pre-upgrade state. You will need to redownload the blockchain"); strLoadError = _("Unable to rewind the database to a pre-upgrade state. You will need to redownload the blockchain");
break; break;
} }
@ -1643,7 +1645,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
RegisterValidationInterface(pwalletMain); RegisterValidationInterface(pwalletMain);
CBlockIndex *pindexRescan = chainActive.Tip(); CBlockIndex *pindexRescan = chainActive.Tip();
if (GetBoolArg("-rescan", false)) if (clearWitnessCaches || GetBoolArg("-rescan", false))
{ {
pwalletMain->ClearNoteWitnessCache(); pwalletMain->ClearNoteWitnessCache();
pindexRescan = chainActive.Genesis(); pindexRescan = chainActive.Genesis();

View File

@ -4217,7 +4217,7 @@ bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth
return true; return true;
} }
bool RewindBlockIndex(const CChainParams& params) bool RewindBlockIndex(const CChainParams& params, bool& clearWitnessCaches)
{ {
LOCK(cs_main); LOCK(cs_main);
@ -4249,23 +4249,45 @@ bool RewindBlockIndex(const CChainParams& params)
// nHeight is now the height of the first insufficiently-validated block, or tipheight + 1 // nHeight is now the height of the first insufficiently-validated block, or tipheight + 1
auto rewindLength = chainActive.Height() - nHeight; auto rewindLength = chainActive.Height() - nHeight;
if (rewindLength > 0 && rewindLength > MAX_REORG_LENGTH) { clearWitnessCaches = false;
auto pindexOldTip = chainActive.Tip();
auto pindexRewind = chainActive[nHeight - 1]; if (rewindLength > 0) {
auto msg = strprintf(_( LogPrintf("*** First insufficiently validated block at height %d, rewind length %d\n", nHeight, rewindLength);
"A block chain rewind has been detected that would roll back %d blocks! " const uint256 *phashFirstInsufValidated = chainActive[nHeight]->phashBlock;
"This is larger than the maximum of %d blocks, and so the node is shutting down for your safety." auto networkID = params.NetworkIDString();
), rewindLength, MAX_REORG_LENGTH) + "\n\n" +
_("Rewind details") + ":\n" + // This is true when we intend to do a long rewind.
"- " + strprintf(_("Current tip: %s, height %d"), bool intendedRewind =
pindexOldTip->phashBlock->GetHex(), pindexOldTip->nHeight) + "\n" + (networkID == "test" && nHeight == 252500 && *phashFirstInsufValidated ==
"- " + strprintf(_("Rewinding to: %s, height %d"), uint256S("0018bd16a9c6f15795a754c498d2b2083ab78f14dae44a66a8d0e90ba8464d9c"));
pindexRewind->phashBlock->GetHex(), pindexRewind->nHeight) + "\n\n" +
_("Please help, human!"); clearWitnessCaches = (rewindLength > MAX_REORG_LENGTH && intendedRewind);
LogPrintf("*** %s\n", msg);
uiInterface.ThreadSafeMessageBox(msg, "", CClientUIInterface::MSG_ERROR); if (clearWitnessCaches) {
StartShutdown(); auto msg = strprintf(_(
return false; "An intended block chain rewind has been detected: network %s, hash %s, height %d"
), networkID, phashFirstInsufValidated->GetHex(), nHeight);
LogPrintf("*** %s\n", msg);
}
if (rewindLength > MAX_REORG_LENGTH && !intendedRewind) {
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; CValidationState state;

View File

@ -478,8 +478,11 @@ bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBloc
* When there are blocks in the active chain with missing data (e.g. if the * When there are blocks in the active chain with missing data (e.g. if the
* activation height and branch ID of a particular upgrade have been altered), * activation height and branch ID of a particular upgrade have been altered),
* rewind the chainstate and remove them from the block index. * rewind the chainstate and remove them from the block index.
*
* clearWitnessCaches is an output parameter that will be set to true iff
* witness caches should be cleared in order to handle an intended long rewind.
*/ */
bool RewindBlockIndex(const CChainParams& params); bool RewindBlockIndex(const CChainParams& params, bool& clearWitnessCaches);
class CBlockFileInfo class CBlockFileInfo
{ {