Detect any sufficiently long fork and add a warning.
Such a fork is defined as being at least 7 blocks long and having a tip which is within 72 blocks of our best block.
This commit is contained in:
parent
4eab2dcc81
commit
b8585384da
1 changed files with 56 additions and 5 deletions
61
src/main.cpp
61
src/main.cpp
|
@ -1383,6 +1383,56 @@ bool IsInitialBlockDownload()
|
|||
pindexBest->GetBlockTime() < GetTime() - 24 * 60 * 60);
|
||||
}
|
||||
|
||||
bool fLargeWorkForkFound = false;
|
||||
CBlockIndex *pindexBestForkTip = NULL, *pindexBestForkBase = NULL;
|
||||
|
||||
void CheckForkWarningConditions()
|
||||
{
|
||||
// If our best fork is no longer within 72 blocks (+/- 12 hours if no one mines it)
|
||||
// of our head, drop it
|
||||
if (pindexBestForkTip && nBestHeight - pindexBestForkTip->nHeight >= 72)
|
||||
pindexBestForkTip = NULL;
|
||||
|
||||
if (pindexBestForkTip || nBestInvalidWork > nBestChainWork + (pindexBest->GetBlockWork() * 6).getuint256())
|
||||
{
|
||||
fLargeWorkForkFound = true;
|
||||
printf("CheckForkWarningConditions: Warning: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade.\n");
|
||||
} else
|
||||
fLargeWorkForkFound = false;
|
||||
}
|
||||
|
||||
void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip)
|
||||
{
|
||||
// If we are on a fork that is sufficiently large, set a warning flag
|
||||
CBlockIndex* pfork = pindexNewForkTip;
|
||||
CBlockIndex* plonger = pindexBest;
|
||||
while (pfork && pfork != plonger)
|
||||
{
|
||||
while (plonger && plonger->nHeight > pfork->nHeight)
|
||||
plonger = plonger->pprev;
|
||||
if (pfork == plonger)
|
||||
break;
|
||||
pfork = pfork->pprev;
|
||||
}
|
||||
|
||||
// We define a condition which we should warn the user about as a fork of at least 7 blocks
|
||||
// who's tip is within 72 blocks (+/- 12 hours if no one mines it) of ours
|
||||
// We use 7 blocks rather arbitrarily as it represents just under 10% of sustained network
|
||||
// hash rate operating on the fork.
|
||||
// or a chain that is entirely longer than ours and invalid (note that this should be detected by both)
|
||||
// We define it this way because it allows us to only store the highest fork tip (+ base) which meets
|
||||
// the 7-block condition and from this always have the most-likely-to-cause-warning fork
|
||||
if (pfork && (!pindexBestForkTip || (pindexBestForkTip && pindexNewForkTip->nHeight > pindexBestForkTip->nHeight)) &&
|
||||
pindexNewForkTip->nChainWork - pfork->nChainWork > (pfork->GetBlockWork() * 7).getuint256() &&
|
||||
nBestHeight - pindexNewForkTip->nHeight < 72)
|
||||
{
|
||||
pindexBestForkTip = pindexNewForkTip;
|
||||
pindexBestForkBase = pfork;
|
||||
}
|
||||
|
||||
CheckForkWarningConditions();
|
||||
}
|
||||
|
||||
void static InvalidChainFound(CBlockIndex* pindexNew)
|
||||
{
|
||||
if (pindexNew->nChainWork > nBestInvalidWork)
|
||||
|
@ -1398,8 +1448,7 @@ void static InvalidChainFound(CBlockIndex* pindexNew)
|
|||
printf("InvalidChainFound: current best=%s height=%d log2_work=%.8g date=%s\n",
|
||||
hashBestChain.ToString().c_str(), nBestHeight, log(nBestChainWork.getdouble())/log(2.0),
|
||||
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", pindexBest->GetBlockTime()).c_str());
|
||||
if (pindexBest && nBestInvalidWork > nBestChainWork + (pindexBest->GetBlockWork() * 6).getuint256())
|
||||
printf("InvalidChainFound: Warning: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade.\n");
|
||||
CheckForkWarningConditions();
|
||||
}
|
||||
|
||||
void static InvalidBlockFound(CBlockIndex *pindex) {
|
||||
|
@ -2110,11 +2159,14 @@ bool AddToBlockIndex(CBlock& block, CValidationState& state, const CDiskBlockPos
|
|||
|
||||
if (pindexNew == pindexBest)
|
||||
{
|
||||
// Clear fork warning if its no longer applicable
|
||||
CheckForkWarningConditions();
|
||||
// Notify UI to display prev block's coinbase if it was ours
|
||||
static uint256 hashPrevBestCoinBase;
|
||||
UpdatedTransaction(hashPrevBestCoinBase);
|
||||
hashPrevBestCoinBase = block.GetTxHash(0);
|
||||
}
|
||||
} else
|
||||
CheckForkWarningConditionsOnNewFork(pindexNew);
|
||||
|
||||
if (!pblocktree->Flush())
|
||||
return state.Abort(_("Failed to sync block index"));
|
||||
|
@ -3073,8 +3125,7 @@ string GetWarnings(string strFor)
|
|||
strStatusBar = strMiscWarning;
|
||||
}
|
||||
|
||||
// Longer invalid proof-of-work chain
|
||||
if (pindexBest && nBestInvalidWork > nBestChainWork + (pindexBest->GetBlockWork() * 6).getuint256())
|
||||
if (fLargeWorkForkFound)
|
||||
{
|
||||
nPriority = 2000;
|
||||
strStatusBar = strRPC = _("Warning: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade.");
|
||||
|
|
Loading…
Add table
Reference in a new issue