@ -1376,6 +1376,82 @@ bool IsInitialBlockDownload()
pindexBest - > GetBlockTime ( ) < GetTime ( ) - 24 * 60 * 60 ) ;
}
bool fLargeWorkForkFound = false ;
bool fLargeWorkInvalidChainFound = 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 ( ) )
{
if ( ! fLargeWorkForkFound )
{
std : : string strCmd = GetArg ( " -alertnotify " , " " ) ;
if ( ! strCmd . empty ( ) )
{
std : : string warning = std : : string ( " 'Warning: Large-work fork detected, forking after block " ) +
pindexBestForkBase - > phashBlock - > ToString ( ) + std : : string ( " ' " ) ;
boost : : replace_all ( strCmd , " %s " , warning ) ;
boost : : thread t ( runCommand , strCmd ) ; // thread runs free
}
}
if ( pindexBestForkTip )
{
printf ( " CheckForkWarningConditions: Warning: Large valid fork found \n forking the chain at height %d (%s) \n lasting to height %d (%s). \n Chain state database corruption likely. \n " ,
pindexBestForkBase - > nHeight , pindexBestForkBase - > phashBlock - > ToString ( ) . c_str ( ) ,
pindexBestForkTip - > nHeight , pindexBestForkTip - > phashBlock - > ToString ( ) . c_str ( ) ) ;
fLargeWorkForkFound = true ;
}
else
{
printf ( " CheckForkWarningConditions: Warning: Found invalid chain at least ~6 blocks longer than our best chain. \n Chain state database corruption likely. \n " ) ;
fLargeWorkInvalidChainFound = true ;
}
}
else
{
fLargeWorkForkFound = false ;
fLargeWorkInvalidChainFound = 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 )
@ -1391,8 +1467,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 ) {
@ -2103,11 +2178,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 " ) ) ;
@ -3066,11 +3144,15 @@ 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: The network does not appear to fully agree! Some miners appear to be experiencing issues. " ) ;
}
else if ( fLargeWorkInvalidChainFound )
{
nPriority = 2000 ;
strStatusBar = strRPC = _ ( " Warning: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade. " ) ;
strStatusBar = strRPC = _ ( " Warning: We do not appear to fully agree with our peers ! You may need to upgrade, or other nodes may need to upgrade." ) ;
}
// Alerts