@ -32,13 +32,8 @@ CTxMemPool mempool;
unsigned int nTransactionsUpdated = 0 ;
unsigned int nTransactionsUpdated = 0 ;
map < uint256 , CBlockIndex * > mapBlockIndex ;
map < uint256 , CBlockIndex * > mapBlockIndex ;
std : : vector < CBlockIndex * > vBlockIndexByHeight ;
CChain chainActive ;
CBlockIndex * pindexGenesisBlock = NULL ;
int nBestHeight = - 1 ;
uint256 nBestChainWork = 0 ;
uint256 nBestInvalidWork = 0 ;
uint256 nBestInvalidWork = 0 ;
uint256 hashBestChain = 0 ;
CBlockIndex * pindexBest = NULL ;
set < CBlockIndex * , CBlockIndexWorkComparator > setBlockIndexValid ; // may contain all CBlockIndex*'s that have validness >=BLOCK_VALID_TRANSACTIONS, and must contain those who aren't failed
set < CBlockIndex * , CBlockIndexWorkComparator > setBlockIndexValid ; // may contain all CBlockIndex*'s that have validness >=BLOCK_VALID_TRANSACTIONS, and must contain those who aren't failed
int64 nTimeBestReceived = 0 ;
int64 nTimeBestReceived = 0 ;
int nScriptCheckThreads = 0 ;
int nScriptCheckThreads = 0 ;
@ -173,14 +168,22 @@ void static ResendWalletTransactions()
// Registration of network node signals.
// Registration of network node signals.
//
//
int static GetHeight ( )
{
LOCK ( cs_main ) ;
return chainActive . Height ( ) ;
}
void RegisterNodeSignals ( CNodeSignals & nodeSignals )
void RegisterNodeSignals ( CNodeSignals & nodeSignals )
{
{
nodeSignals . GetHeight . connect ( & GetHeight ) ;
nodeSignals . ProcessMessages . connect ( & ProcessMessages ) ;
nodeSignals . ProcessMessages . connect ( & ProcessMessages ) ;
nodeSignals . SendMessages . connect ( & SendMessages ) ;
nodeSignals . SendMessages . connect ( & SendMessages ) ;
}
}
void UnregisterNodeSignals ( CNodeSignals & nodeSignals )
void UnregisterNodeSignals ( CNodeSignals & nodeSignals )
{
{
nodeSignals . GetHeight . disconnect ( & GetHeight ) ;
nodeSignals . ProcessMessages . disconnect ( & ProcessMessages ) ;
nodeSignals . ProcessMessages . disconnect ( & ProcessMessages ) ;
nodeSignals . SendMessages . disconnect ( & SendMessages ) ;
nodeSignals . SendMessages . disconnect ( & SendMessages ) ;
}
}
@ -225,7 +228,7 @@ int CBlockLocator::GetDistanceBack()
if ( mi ! = mapBlockIndex . end ( ) )
if ( mi ! = mapBlockIndex . end ( ) )
{
{
CBlockIndex * pindex = ( * mi ) . second ;
CBlockIndex * pindex = ( * mi ) . second ;
if ( pindex - > IsInMainChain ( ) )
if ( chainActive . Contains ( pindex ) )
return nDistance ;
return nDistance ;
}
}
nDistance + = nStep ;
nDistance + = nStep ;
@ -244,11 +247,11 @@ CBlockIndex *CBlockLocator::GetBlockIndex()
if ( mi ! = mapBlockIndex . end ( ) )
if ( mi ! = mapBlockIndex . end ( ) )
{
{
CBlockIndex * pindex = ( * mi ) . second ;
CBlockIndex * pindex = ( * mi ) . second ;
if ( pindex - > IsInMainChain ( ) )
if ( chainActive . Contains ( pindex ) )
return pindex ;
return pindex ;
}
}
}
}
return pindexGenesisBlock ;
return chainActive . Genesis ( ) ;
}
}
uint256 CBlockLocator : : GetBlockHash ( )
uint256 CBlockLocator : : GetBlockHash ( )
@ -260,7 +263,7 @@ uint256 CBlockLocator::GetBlockHash()
if ( mi ! = mapBlockIndex . end ( ) )
if ( mi ! = mapBlockIndex . end ( ) )
{
{
CBlockIndex * pindex = ( * mi ) . second ;
CBlockIndex * pindex = ( * mi ) . second ;
if ( pindex - > IsInMainChain ( ) )
if ( chainActive . Contains ( pindex ) )
return hash ;
return hash ;
}
}
}
}
@ -275,6 +278,19 @@ int CBlockLocator::GetHeight()
return pindex - > nHeight ;
return pindex - > nHeight ;
}
}
CBlockIndex * CChain : : SetTip ( CBlockIndex * pindex ) {
if ( pindex = = NULL ) {
std : : vector < CBlockIndex * > ( ) . swap ( vChain ) ;
return NULL ;
}
vChain . resize ( pindex - > nHeight + 1 ) ;
while ( pindex & & vChain [ pindex - > nHeight ] ! = pindex ) {
vChain [ pindex - > nHeight ] = pindex ;
pindex = pindex - > pprev ;
}
return pindex ;
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//
//
// CCoinsView implementations
// CCoinsView implementations
@ -517,7 +533,7 @@ bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64 nBlockTime)
if ( tx . nLockTime = = 0 )
if ( tx . nLockTime = = 0 )
return true ;
return true ;
if ( nBlockHeight = = 0 )
if ( nBlockHeight = = 0 )
nBlockHeight = nBestHeight ;
nBlockHeight = chainActive . Height ( ) ;
if ( nBlockTime = = 0 )
if ( nBlockTime = = 0 )
nBlockTime = GetAdjustedTime ( ) ;
nBlockTime = GetAdjustedTime ( ) ;
if ( ( int64 ) tx . nLockTime < ( ( int64 ) tx . nLockTime < LOCKTIME_THRESHOLD ? ( int64 ) nBlockHeight : nBlockTime ) )
if ( ( int64 ) tx . nLockTime < ( ( int64 ) tx . nLockTime < LOCKTIME_THRESHOLD ? ( int64 ) nBlockHeight : nBlockTime ) )
@ -644,7 +660,7 @@ int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
if ( pblock = = NULL ) {
if ( pblock = = NULL ) {
CCoins coins ;
CCoins coins ;
if ( pcoinsTip - > GetCoins ( GetHash ( ) , coins ) ) {
if ( pcoinsTip - > GetCoins ( GetHash ( ) , coins ) ) {
CBlockIndex * pindex = FindBlockByHeight ( coins . nHeight ) ;
CBlockIndex * pindex = chainActive [ coins . nHeight ] ;
if ( pindex ) {
if ( pindex ) {
if ( ! ReadBlockFromDisk ( blockTmp , pindex ) )
if ( ! ReadBlockFromDisk ( blockTmp , pindex ) )
return 0 ;
return 0 ;
@ -678,10 +694,10 @@ int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
if ( mi = = mapBlockIndex . end ( ) )
if ( mi = = mapBlockIndex . end ( ) )
return 0 ;
return 0 ;
CBlockIndex * pindex = ( * mi ) . second ;
CBlockIndex * pindex = ( * mi ) . second ;
if ( ! pindex | | ! pindex - > IsInMainChain ( ) )
if ( ! pindex | | ! chainActive . Contains ( pindex ) )
return 0 ;
return 0 ;
return pindexBest - > nHeight - pindex - > nHeight + 1 ;
return chainActive . Height ( ) - pindex - > nHeight + 1 ;
}
}
@ -1078,7 +1094,7 @@ int CMerkleTx::GetDepthInMainChain(CBlockIndex* &pindexRet) const
if ( mi = = mapBlockIndex . end ( ) )
if ( mi = = mapBlockIndex . end ( ) )
return 0 ;
return 0 ;
CBlockIndex * pindex = ( * mi ) . second ;
CBlockIndex * pindex = ( * mi ) . second ;
if ( ! pindex | | ! pindex - > IsInMainChain ( ) )
if ( ! pindex | | ! chainActive . Contains ( pindex ) )
return 0 ;
return 0 ;
// Make sure the merkle branch connects to this block
// Make sure the merkle branch connects to this block
@ -1090,7 +1106,7 @@ int CMerkleTx::GetDepthInMainChain(CBlockIndex* &pindexRet) const
}
}
pindexRet = pindex ;
pindexRet = pindex ;
return pindexBest - > nHeight - pindex - > nHeight + 1 ;
return chainActive . Height ( ) - pindex - > nHeight + 1 ;
}
}
@ -1173,7 +1189,7 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock
nHeight = coins . nHeight ;
nHeight = coins . nHeight ;
}
}
if ( nHeight > 0 )
if ( nHeight > 0 )
pindexSlow = FindBlockByHeight ( nHeight ) ;
pindexSlow = chainActive [ nHeight ] ;
}
}
}
}
@ -1203,14 +1219,6 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock
// CBlock and CBlockIndex
// CBlock and CBlockIndex
//
//
static CBlockIndex * pblockindexFBBHLast ;
CBlockIndex * FindBlockByHeight ( int nHeight )
{
if ( nHeight > = ( int ) vBlockIndexByHeight . size ( ) )
return NULL ;
return vBlockIndexByHeight [ nHeight ] ;
}
bool WriteBlockToDisk ( CBlock & block , CDiskBlockPos & pos )
bool WriteBlockToDisk ( CBlock & block , CDiskBlockPos & pos )
{
{
// Open history file to append
// Open history file to append
@ -1404,17 +1412,17 @@ int GetNumBlocksOfPeers()
bool IsInitialBlockDownload ( )
bool IsInitialBlockDownload ( )
{
{
if ( pindexBest = = NULL | | fImporting | | fReindex | | nBestHeight < Checkpoints : : GetTotalBlocksEstimate ( ) )
if ( fImporting | | fReindex | | chainActive . Height ( ) < Checkpoints : : GetTotalBlocksEstimate ( ) )
return true ;
return true ;
static int64 nLastUpdate ;
static int64 nLastUpdate ;
static CBlockIndex * pindexLastBest ;
static CBlockIndex * pindexLastBest ;
if ( pindexBest ! = pindexLastBest )
if ( chainActive . Tip ( ) ! = pindexLastBest )
{
{
pindexLastBest = pindexBest ;
pindexLastBest = chainActive . Tip ( ) ;
nLastUpdate = GetTime ( ) ;
nLastUpdate = GetTime ( ) ;
}
}
return ( GetTime ( ) - nLastUpdate < 10 & &
return ( GetTime ( ) - nLastUpdate < 10 & &
pindexBest - > GetBlockTime ( ) < GetTime ( ) - 24 * 60 * 60 ) ;
chainActive . Tip ( ) - > GetBlockTime ( ) < GetTime ( ) - 24 * 60 * 60 ) ;
}
}
bool fLargeWorkForkFound = false ;
bool fLargeWorkForkFound = false ;
@ -1430,10 +1438,10 @@ void CheckForkWarningConditions()
// If our best fork is no longer within 72 blocks (+/- 12 hours if no one mines it)
// If our best fork is no longer within 72 blocks (+/- 12 hours if no one mines it)
// of our head, drop it
// of our head, drop it
if ( pindexBestForkTip & & nBestHeight - pindexBestForkTip - > nHeight > = 72 )
if ( pindexBestForkTip & & chainActive . Height ( ) - pindexBestForkTip - > nHeight > = 72 )
pindexBestForkTip = NULL ;
pindexBestForkTip = NULL ;
if ( pindexBestForkTip | | nBestInvalidWork > nBestChainWork + ( pindexBest - > GetBlockWork ( ) * 6 ) . getuint256 ( ) )
if ( pindexBestForkTip | | nBestInvalidWork > chainActive . Tip ( ) - > nChainWork + ( chainActive . Tip ( ) - > GetBlockWork ( ) * 6 ) . getuint256 ( ) )
{
{
if ( ! fLargeWorkForkFound )
if ( ! fLargeWorkForkFound )
{
{
@ -1470,7 +1478,7 @@ void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip)
{
{
// If we are on a fork that is sufficiently large, set a warning flag
// If we are on a fork that is sufficiently large, set a warning flag
CBlockIndex * pfork = pindexNewForkTip ;
CBlockIndex * pfork = pindexNewForkTip ;
CBlockIndex * plonger = pindexBest ;
CBlockIndex * plonger = chainActive . Tip ( ) ;
while ( pfork & & pfork ! = plonger )
while ( pfork & & pfork ! = plonger )
{
{
while ( plonger & & plonger - > nHeight > pfork - > nHeight )
while ( plonger & & plonger - > nHeight > pfork - > nHeight )
@ -1489,7 +1497,7 @@ void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip)
// the 7-block condition and from this always have the most-likely-to-cause-warning fork
// the 7-block condition and from this always have the most-likely-to-cause-warning fork
if ( pfork & & ( ! pindexBestForkTip | | ( pindexBestForkTip & & pindexNewForkTip - > nHeight > pindexBestForkTip - > nHeight ) ) & &
if ( pfork & & ( ! pindexBestForkTip | | ( pindexBestForkTip & & pindexNewForkTip - > nHeight > pindexBestForkTip - > nHeight ) ) & &
pindexNewForkTip - > nChainWork - pfork - > nChainWork > ( pfork - > GetBlockWork ( ) * 7 ) . getuint256 ( ) & &
pindexNewForkTip - > nChainWork - pfork - > nChainWork > ( pfork - > GetBlockWork ( ) * 7 ) . getuint256 ( ) & &
nBestHeight - pindexNewForkTip - > nHeight < 72 )
chainActive . Height ( ) - pindexNewForkTip - > nHeight < 72 )
{
{
pindexBestForkTip = pindexNewForkTip ;
pindexBestForkTip = pindexNewForkTip ;
pindexBestForkBase = pfork ;
pindexBestForkBase = pfork ;
@ -1511,8 +1519,8 @@ void static InvalidChainFound(CBlockIndex* pindexNew)
log ( pindexNew - > nChainWork . getdouble ( ) ) / log ( 2.0 ) , DateTimeStrFormat ( " %Y-%m-%d %H:%M:%S " ,
log ( pindexNew - > nChainWork . getdouble ( ) ) / log ( 2.0 ) , DateTimeStrFormat ( " %Y-%m-%d %H:%M:%S " ,
pindexNew - > GetBlockTime ( ) ) . c_str ( ) ) ;
pindexNew - > GetBlockTime ( ) ) . c_str ( ) ) ;
LogPrintf ( " InvalidChainFound: current best=%s height=%d log2_work=%.8g date=%s \n " ,
LogPrintf ( " InvalidChainFound: current best=%s height=%d log2_work=%.8g date=%s \n " ,
hashBestChain . ToString ( ) . c_str ( ) , nBestHeight , log ( nBest ChainWork. getdouble ( ) ) / log ( 2.0 ) ,
chainActive . Tip ( ) - > GetBlockHash ( ) . ToString ( ) . c_str ( ) , chainActive . Height ( ) , log ( chainActive . Tip ( ) - > n ChainWork. getdouble ( ) ) / log ( 2.0 ) ,
DateTimeStrFormat ( " %Y-%m-%d %H:%M:%S " , pindexBest - > GetBlockTime ( ) ) . c_str ( ) ) ;
DateTimeStrFormat ( " %Y-%m-%d %H:%M:%S " , chainActive . Tip ( ) - > GetBlockTime ( ) ) . c_str ( ) ) ;
CheckForkWarningConditions ( ) ;
CheckForkWarningConditions ( ) ;
}
}
@ -1521,7 +1529,7 @@ void static InvalidBlockFound(CBlockIndex *pindex) {
pblocktree - > WriteBlockIndex ( CDiskBlockIndex ( pindex ) ) ;
pblocktree - > WriteBlockIndex ( CDiskBlockIndex ( pindex ) ) ;
setBlockIndexValid . erase ( pindex ) ;
setBlockIndexValid . erase ( pindex ) ;
InvalidChainFound ( pindex ) ;
InvalidChainFound ( pindex ) ;
if ( pindex - > GetNextInMainChain ( ) ) {
if ( chainActive . Next ( pindex ) ) {
CValidationState stateDummy ;
CValidationState stateDummy ;
ConnectBestBlock ( stateDummy ) ; // reorganise away from the failed block
ConnectBestBlock ( stateDummy ) ; // reorganise away from the failed block
}
}
@ -1538,7 +1546,7 @@ bool ConnectBestBlock(CValidationState &state) {
pindexNewBest = * it ;
pindexNewBest = * it ;
}
}
if ( pindexNewBest = = pindexBest | | ( pindexBest & & pindexNewBest - > nChainWork = = pindexBest - > nChainWork ) )
if ( pindexNewBest = = chainActive . Tip ( ) | | ( chainActive . Tip ( ) & & pindexNewBest - > nChainWork = = chainActive . Tip ( ) - > nChainWork ) )
return true ; // nothing to do
return true ; // nothing to do
// check ancestry
// check ancestry
@ -1558,10 +1566,10 @@ bool ConnectBestBlock(CValidationState &state) {
break ;
break ;
}
}
if ( pindexBest = = NULL | | pindexTest - > nChainWork > pindexBest - > nChainWork )
if ( chainActive . Tip ( ) = = NULL | | pindexTest - > nChainWork > chainActive . Tip ( ) - > nChainWork )
vAttach . push_back ( pindexTest ) ;
vAttach . push_back ( pindexTest ) ;
if ( pindexTest - > pprev = = NULL | | pindexTest - > GetNextInMainChain ( ) ) {
if ( pindexTest - > pprev = = NULL | | chainActive . Next ( pindexTest ) ) {
reverse ( vAttach . begin ( ) , vAttach . end ( ) ) ;
reverse ( vAttach . begin ( ) , vAttach . end ( ) ) ;
BOOST_FOREACH ( CBlockIndex * pindexSwitch , vAttach ) {
BOOST_FOREACH ( CBlockIndex * pindexSwitch , vAttach ) {
boost : : this_thread : : interruption_point ( ) ;
boost : : this_thread : : interruption_point ( ) ;
@ -1881,7 +1889,6 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
// (its coinbase is unspendable)
// (its coinbase is unspendable)
if ( block . GetHash ( ) = = Params ( ) . HashGenesisBlock ( ) ) {
if ( block . GetHash ( ) = = Params ( ) . HashGenesisBlock ( ) ) {
view . SetBestBlock ( pindex ) ;
view . SetBestBlock ( pindex ) ;
pindexGenesisBlock = pindex ;
return true ;
return true ;
}
}
@ -2129,9 +2136,7 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
// Proceed by updating the memory structures.
// Proceed by updating the memory structures.
// Register new best chain
// Register new best chain
vBlockIndexByHeight . resize ( pindexNew - > nHeight + 1 ) ;
chainActive . SetTip ( pindexNew ) ;
BOOST_FOREACH ( CBlockIndex * pindex , vConnect )
vBlockIndexByHeight [ pindex - > nHeight ] = pindex ;
// Resurrect memory transactions that were in the disconnected branch
// Resurrect memory transactions that were in the disconnected branch
BOOST_FOREACH ( CTransaction & tx , vResurrect ) {
BOOST_FOREACH ( CTransaction & tx , vResurrect ) {
@ -2157,23 +2162,18 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
}
}
// New best block
// New best block
hashBestChain = pindexNew - > GetBlockHash ( ) ;
pindexBest = pindexNew ;
pblockindexFBBHLast = NULL ;
nBestHeight = pindexBest - > nHeight ;
nBestChainWork = pindexNew - > nChainWork ;
nTimeBestReceived = GetTime ( ) ;
nTimeBestReceived = GetTime ( ) ;
nTransactionsUpdated + + ;
nTransactionsUpdated + + ;
LogPrintf ( " SetBestChain: new best=%s height=%d log2_work=%.8g tx=%lu date=%s progress=%f \n " ,
LogPrintf ( " SetBestChain: new best=%s height=%d log2_work=%.8g tx=%lu date=%s progress=%f \n " ,
hashBestChain . ToString ( ) . c_str ( ) , nBestHeight , log ( nBest ChainWork. getdouble ( ) ) / log ( 2.0 ) , ( unsigned long ) pindexNew - > nChainTx ,
chainActive . Tip ( ) - > GetBlockHash ( ) . ToString ( ) . c_str ( ) , chainActive . Height ( ) , log ( chainActive . Tip ( ) - > nChainWork . getdouble ( ) ) / log ( 2.0 ) , ( unsigned long ) pindexNew - > nChainTx ,
DateTimeStrFormat ( " %Y-%m-%d %H:%M:%S " , pindexBest - > GetBlockTime ( ) ) . c_str ( ) ,
DateTimeStrFormat ( " %Y-%m-%d %H:%M:%S " , chainActive . Tip ( ) - > GetBlockTime ( ) ) . c_str ( ) ,
Checkpoints : : GuessVerificationProgress ( pindexBest ) ) ;
Checkpoints : : GuessVerificationProgress ( chainActive . Tip ( ) ) ) ;
// Check the version of the last 100 blocks to see if we need to upgrade:
// Check the version of the last 100 blocks to see if we need to upgrade:
if ( ! fIsInitialDownload )
if ( ! fIsInitialDownload )
{
{
int nUpgraded = 0 ;
int nUpgraded = 0 ;
const CBlockIndex * pindex = pindexBest ;
const CBlockIndex * pindex = chainActive . Tip ( ) ;
for ( int i = 0 ; i < 100 & & pindex ! = NULL ; i + + )
for ( int i = 0 ; i < 100 & & pindex ! = NULL ; i + + )
{
{
if ( pindex - > nVersion > CBlock : : CURRENT_VERSION )
if ( pindex - > nVersion > CBlock : : CURRENT_VERSION )
@ -2191,7 +2191,7 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
if ( ! fIsInitialDownload & & ! strCmd . empty ( ) )
if ( ! fIsInitialDownload & & ! strCmd . empty ( ) )
{
{
boost : : replace_all ( strCmd , " %s " , hashBestChain . GetHex ( ) ) ;
boost : : replace_all ( strCmd , " %s " , chainActive . Tip ( ) - > GetBlockHash ( ) . GetHex ( ) ) ;
boost : : thread t ( runCommand , strCmd ) ; // thread runs free
boost : : thread t ( runCommand , strCmd ) ; // thread runs free
}
}
@ -2233,7 +2233,7 @@ bool AddToBlockIndex(CBlock& block, CValidationState& state, const CDiskBlockPos
if ( ! ConnectBestBlock ( state ) )
if ( ! ConnectBestBlock ( state ) )
return false ;
return false ;
if ( pindexNew = = pindexBest )
if ( pindexNew = = chainActive . Tip ( ) )
{
{
// Clear fork warning if its no longer applicable
// Clear fork warning if its no longer applicable
CheckForkWarningConditions ( ) ;
CheckForkWarningConditions ( ) ;
@ -2482,11 +2482,11 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CDiskBlockPos* dbp)
// Relay inventory, but don't relay old inventory during initial block download
// Relay inventory, but don't relay old inventory during initial block download
int nBlockEstimate = Checkpoints : : GetTotalBlocksEstimate ( ) ;
int nBlockEstimate = Checkpoints : : GetTotalBlocksEstimate ( ) ;
if ( hashBestChain = = hash )
if ( chainActive . Tip ( ) - > GetBlockHash ( ) = = hash )
{
{
LOCK ( cs_vNodes ) ;
LOCK ( cs_vNodes ) ;
BOOST_FOREACH ( CNode * pnode , vNodes )
BOOST_FOREACH ( CNode * pnode , vNodes )
if ( nBestHeight > ( pnode - > nStartingHeight ! = - 1 ? pnode - > nStartingHeight - 2000 : nBlockEstimate ) )
if ( chainActive . Height ( ) > ( pnode - > nStartingHeight ! = - 1 ? pnode - > nStartingHeight - 2000 : nBlockEstimate ) )
pnode - > PushInventory ( CInv ( MSG_BLOCK , hash ) ) ;
pnode - > PushInventory ( CInv ( MSG_BLOCK , hash ) ) ;
}
}
@ -2505,6 +2505,18 @@ bool CBlockIndex::IsSuperMajority(int minVersion, const CBlockIndex* pstart, uns
return ( nFound > = nRequired ) ;
return ( nFound > = nRequired ) ;
}
}
int64 CBlockIndex : : GetMedianTime ( ) const
{
const CBlockIndex * pindex = this ;
for ( int i = 0 ; i < nMedianTimeSpan / 2 ; i + + )
{
if ( ! chainActive . Next ( pindex ) )
return GetBlockTime ( ) ;
pindex = chainActive . Next ( pindex ) ;
}
return pindex - > GetMedianTimePast ( ) ;
}
void PushGetBlocks ( CNode * pnode , CBlockIndex * pindexBegin , uint256 hashEnd )
void PushGetBlocks ( CNode * pnode , CBlockIndex * pindexBegin , uint256 hashEnd )
{
{
// Filter out duplicate requests
// Filter out duplicate requests
@ -2530,7 +2542,7 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl
return error ( " ProcessBlock() : CheckBlock FAILED " ) ;
return error ( " ProcessBlock() : CheckBlock FAILED " ) ;
CBlockIndex * pcheckpoint = Checkpoints : : GetLastCheckpoint ( mapBlockIndex ) ;
CBlockIndex * pcheckpoint = Checkpoints : : GetLastCheckpoint ( mapBlockIndex ) ;
if ( pcheckpoint & & pblock - > hashPrevBlock ! = hashBestChain )
if ( pcheckpoint & & pblock - > hashPrevBlock ! = ( chainActive . Tip ( ) ? chainActive . Tip ( ) - > GetBlockHash ( ) : uint256 ( 0 ) ) )
{
{
// Extra checks to prevent "fill up memory by spamming with bogus blocks"
// Extra checks to prevent "fill up memory by spamming with bogus blocks"
int64 deltaTime = pblock - > GetBlockTime ( ) - pcheckpoint - > nTime ;
int64 deltaTime = pblock - > GetBlockTime ( ) - pcheckpoint - > nTime ;
@ -2561,7 +2573,7 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl
mapOrphanBlocksByPrev . insert ( make_pair ( pblock2 - > hashPrevBlock , pblock2 ) ) ;
mapOrphanBlocksByPrev . insert ( make_pair ( pblock2 - > hashPrevBlock , pblock2 ) ) ;
// Ask this guy to fill in what we're missing
// Ask this guy to fill in what we're missing
PushGetBlocks ( pfrom , pindexBest , GetOrphanRoot ( pblock2 ) ) ;
PushGetBlocks ( pfrom , chainActive . Tip ( ) , GetOrphanRoot ( pblock2 ) ) ;
}
}
return true ;
return true ;
}
}
@ -2875,48 +2887,39 @@ bool static LoadBlockIndexDB()
LogPrintf ( " LoadBlockIndexDB(): transaction index %s \n " , fTxIndex ? " enabled " : " disabled " ) ;
LogPrintf ( " LoadBlockIndexDB(): transaction index %s \n " , fTxIndex ? " enabled " : " disabled " ) ;
// Load hashBestChain pointer to end of best chain
// Load hashBestChain pointer to end of best chain
pindexBest = pcoinsTip - > GetBestBlock ( ) ;
chainActive . SetTip ( pcoinsTip - > GetBestBlock ( ) ) ;
if ( pindexBest = = NULL )
if ( chainActive . Tip ( ) = = NULL )
return true ;
return true ;
hashBestChain = pindexBest - > GetBlockHash ( ) ;
nBestHeight = pindexBest - > nHeight ;
nBestChainWork = pindexBest - > nChainWork ;
// register best chain
// register best chain
CBlockIndex * pindex = pindexBest ;
vBlockIndexByHeight . resize ( pindexBest - > nHeight + 1 ) ;
while ( pindex ! = NULL ) {
vBlockIndexByHeight [ pindex - > nHeight ] = pindex ;
pindex = pindex - > pprev ;
}
LogPrintf ( " LoadBlockIndexDB(): hashBestChain=%s height=%d date=%s \n " ,
LogPrintf ( " LoadBlockIndexDB(): hashBestChain=%s height=%d date=%s \n " ,
hashBestChain . ToString ( ) . c_str ( ) , nBestHeight ,
chainActive . Tip ( ) - > GetBlockHash ( ) . ToString ( ) . c_str ( ) , chainActive . Height ( ) ,
DateTimeStrFormat ( " %Y-%m-%d %H:%M:%S " , pindexBest - > GetBlockTime ( ) ) . c_str ( ) ) ;
DateTimeStrFormat ( " %Y-%m-%d %H:%M:%S " , chainActive . Tip ( ) - > GetBlockTime ( ) ) . c_str ( ) ) ;
return true ;
return true ;
}
}
bool VerifyDB ( int nCheckLevel , int nCheckDepth )
bool VerifyDB ( int nCheckLevel , int nCheckDepth )
{
{
if ( pindexBest = = NULL | | pindexBest - > pprev = = NULL )
if ( chainActive . Tip ( ) = = NULL | | chainActive . Tip ( ) - > pprev = = NULL )
return true ;
return true ;
// Verify blocks in the best chain
// Verify blocks in the best chain
if ( nCheckDepth < = 0 )
if ( nCheckDepth < = 0 )
nCheckDepth = 1000000000 ; // suffices until the year 19000
nCheckDepth = 1000000000 ; // suffices until the year 19000
if ( nCheckDepth > nBestHeight )
if ( nCheckDepth > chainActive . Height ( ) )
nCheckDepth = nBestHeight ;
nCheckDepth = chainActive . Height ( ) ;
nCheckLevel = std : : max ( 0 , std : : min ( 4 , nCheckLevel ) ) ;
nCheckLevel = std : : max ( 0 , std : : min ( 4 , nCheckLevel ) ) ;
LogPrintf ( " Verifying last %i blocks at level %i \n " , nCheckDepth , nCheckLevel ) ;
LogPrintf ( " Verifying last %i blocks at level %i \n " , nCheckDepth , nCheckLevel ) ;
CCoinsViewCache coins ( * pcoinsTip , true ) ;
CCoinsViewCache coins ( * pcoinsTip , true ) ;
CBlockIndex * pindexState = pindexBest ;
CBlockIndex * pindexState = chainActive . Tip ( ) ;
CBlockIndex * pindexFailure = NULL ;
CBlockIndex * pindexFailure = NULL ;
int nGoodTransactions = 0 ;
int nGoodTransactions = 0 ;
CValidationState state ;
CValidationState state ;
for ( CBlockIndex * pindex = pindexBest ; pindex & & pindex - > pprev ; pindex = pindex - > pprev )
for ( CBlockIndex * pindex = chainActive . Tip ( ) ; pindex & & pindex - > pprev ; pindex = pindex - > pprev )
{
{
boost : : this_thread : : interruption_point ( ) ;
boost : : this_thread : : interruption_point ( ) ;
if ( pindex - > nHeight < nBestHeight - nCheckDepth )
if ( pindex - > nHeight < chainActive . Height ( ) - nCheckDepth )
break ;
break ;
CBlock block ;
CBlock block ;
// check level 0: read from disk
// check level 0: read from disk
@ -2948,14 +2951,14 @@ bool VerifyDB(int nCheckLevel, int nCheckDepth)
}
}
}
}
if ( pindexFailure )
if ( pindexFailure )
return error ( " VerifyDB() : * * * coin database inconsistencies found ( last % i blocks , % i good transactions before that ) \ n " , pindexBest->nHeight - pindexFailure->nHeight + 1, nGoodTransactions) ;
return error ( " VerifyDB() : * * * coin database inconsistencies found ( last % i blocks , % i good transactions before that ) \ n " , chainActive.Height() - pindexFailure->nHeight + 1, nGoodTransactions) ;
// check level 4: try reconnecting blocks
// check level 4: try reconnecting blocks
if ( nCheckLevel > = 4 ) {
if ( nCheckLevel > = 4 ) {
CBlockIndex * pindex = pindexState ;
CBlockIndex * pindex = pindexState ;
while ( pindex ! = pindexBest ) {
while ( pindex ! = chainActive . Tip ( ) ) {
boost : : this_thread : : interruption_point ( ) ;
boost : : this_thread : : interruption_point ( ) ;
pindex = pindex - > GetNextInMainChain ( ) ;
pindex = chainActive . Next ( pindex ) ;
CBlock block ;
CBlock block ;
if ( ! ReadBlockFromDisk ( block , pindex ) )
if ( ! ReadBlockFromDisk ( block , pindex ) )
return error ( " VerifyDB() : * * * ReadBlockFromDisk failed at % d , hash = % s " , pindex->nHeight, pindex->GetBlockHash().ToString().c_str()) ;
return error ( " VerifyDB() : * * * ReadBlockFromDisk failed at % d , hash = % s " , pindex->nHeight, pindex->GetBlockHash().ToString().c_str()) ;
@ -2964,7 +2967,7 @@ bool VerifyDB(int nCheckLevel, int nCheckDepth)
}
}
}
}
LogPrintf ( " No coin database inconsistencies in last %i blocks (%i transactions) \n " , pindexBest - > nHeight - pindexState - > nHeight , nGoodTransactions ) ;
LogPrintf ( " No coin database inconsistencies in last %i blocks (%i transactions) \n " , chainActive . Height ( ) - pindexState - > nHeight , nGoodTransactions ) ;
return true ;
return true ;
}
}
@ -2973,12 +2976,8 @@ void UnloadBlockIndex()
{
{
mapBlockIndex . clear ( ) ;
mapBlockIndex . clear ( ) ;
setBlockIndexValid . clear ( ) ;
setBlockIndexValid . clear ( ) ;
pindexGenesisBlock = NULL ;
chainActive . SetTip ( NULL ) ;
nBestHeight = 0 ;
nBestChainWork = 0 ;
nBestInvalidWork = 0 ;
nBestInvalidWork = 0 ;
hashBestChain = 0 ;
pindexBest = NULL ;
}
}
bool LoadBlockIndex ( )
bool LoadBlockIndex ( )
@ -2992,7 +2991,7 @@ bool LoadBlockIndex()
bool InitBlockIndex ( ) {
bool InitBlockIndex ( ) {
// Check whether we're already initialized
// Check whether we're already initialized
if ( pindexGenesisBlock ! = NULL )
if ( chainActive . Genesis ( ) ! = NULL )
return true ;
return true ;
// Use the provided setting for -txindex in the new database
// Use the provided setting for -txindex in the new database
@ -3038,7 +3037,7 @@ void PrintBlockTree()
}
}
vector < pair < int , CBlockIndex * > > vStack ;
vector < pair < int , CBlockIndex * > > vStack ;
vStack . push_back ( make_pair ( 0 , pindexGenesisBlock ) ) ;
vStack . push_back ( make_pair ( 0 , chainActive . Genesis ( ) ) ) ;
int nPrevCol = 0 ;
int nPrevCol = 0 ;
while ( ! vStack . empty ( ) )
while ( ! vStack . empty ( ) )
@ -3081,7 +3080,7 @@ void PrintBlockTree()
vector < CBlockIndex * > & vNext = mapNext [ pindex ] ;
vector < CBlockIndex * > & vNext = mapNext [ pindex ] ;
for ( unsigned int i = 0 ; i < vNext . size ( ) ; i + + )
for ( unsigned int i = 0 ; i < vNext . size ( ) ; i + + )
{
{
if ( vNext [ i ] - > GetNextInMainChain ( ) )
if ( chainActive . Next ( vNext [ i ] ) )
{
{
swap ( vNext [ 0 ] , vNext [ i ] ) ;
swap ( vNext [ 0 ] , vNext [ i ] ) ;
break ;
break ;
@ -3328,7 +3327,7 @@ void static ProcessGetData(CNode* pfrom)
// and we want it right after the last block so they don't
// and we want it right after the last block so they don't
// wait for other stuff first.
// wait for other stuff first.
vector < CInv > vInv ;
vector < CInv > vInv ;
vInv . push_back ( CInv ( MSG_BLOCK , hashBestChain ) ) ;
vInv . push_back ( CInv ( MSG_BLOCK , chainActive . Tip ( ) - > GetBlockHash ( ) ) ) ;
pfrom - > PushMessage ( " inv " , vInv ) ;
pfrom - > PushMessage ( " inv " , vInv ) ;
pfrom - > hashContinue = 0 ;
pfrom - > hashContinue = 0 ;
}
}
@ -3610,7 +3609,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
if ( ! fImporting & & ! fReindex )
if ( ! fImporting & & ! fReindex )
pfrom - > AskFor ( inv ) ;
pfrom - > AskFor ( inv ) ;
} else if ( inv . type = = MSG_BLOCK & & mapOrphanBlocks . count ( inv . hash ) ) {
} else if ( inv . type = = MSG_BLOCK & & mapOrphanBlocks . count ( inv . hash ) ) {
PushGetBlocks ( pfrom , pindexBest , GetOrphanRoot ( mapOrphanBlocks [ inv . hash ] ) ) ;
PushGetBlocks ( pfrom , chainActive . Tip ( ) , GetOrphanRoot ( mapOrphanBlocks [ inv . hash ] ) ) ;
} else if ( nInv = = nLastBlock ) {
} else if ( nInv = = nLastBlock ) {
// In case we are on a very long side-chain, it is possible that we already have
// In case we are on a very long side-chain, it is possible that we already have
// the last block in an inv bundle sent in response to getblocks. Try to detect
// the last block in an inv bundle sent in response to getblocks. Try to detect
@ -3658,10 +3657,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
// Send the rest of the chain
// Send the rest of the chain
if ( pindex )
if ( pindex )
pindex = pindex - > GetNextInMainChain ( ) ;
pindex = chainActive . Next ( pindex ) ;
int nLimit = 500 ;
int nLimit = 500 ;
LogPrint ( " net " , " getblocks %d to %s limit %d \n " , ( pindex ? pindex - > nHeight : - 1 ) , hashStop . ToString ( ) . c_str ( ) , nLimit ) ;
LogPrint ( " net " , " getblocks %d to %s limit %d \n " , ( pindex ? pindex - > nHeight : - 1 ) , hashStop . ToString ( ) . c_str ( ) , nLimit ) ;
for ( ; pindex ; pindex = pindex - > GetNextInMainChain ( ) )
for ( ; pindex ; pindex = chainActive . Next ( pindex ) )
{
{
if ( pindex - > GetBlockHash ( ) = = hashStop )
if ( pindex - > GetBlockHash ( ) = = hashStop )
{
{
@ -3701,14 +3700,14 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
// Find the last block the caller has in the main chain
// Find the last block the caller has in the main chain
pindex = locator . GetBlockIndex ( ) ;
pindex = locator . GetBlockIndex ( ) ;
if ( pindex )
if ( pindex )
pindex = pindex - > GetNextInMainChain ( ) ;
pindex = chainActive . Next ( pindex ) ;
}
}
// we must use CBlocks, as CBlockHeaders won't include the 0x00 nTx count at the end
// we must use CBlocks, as CBlockHeaders won't include the 0x00 nTx count at the end
vector < CBlock > vHeaders ;
vector < CBlock > vHeaders ;
int nLimit = 2000 ;
int nLimit = 2000 ;
LogPrint ( " net " , " getheaders %d to %s \n " , ( pindex ? pindex - > nHeight : - 1 ) , hashStop . ToString ( ) . c_str ( ) ) ;
LogPrint ( " net " , " getheaders %d to %s \n " , ( pindex ? pindex - > nHeight : - 1 ) , hashStop . ToString ( ) . c_str ( ) ) ;
for ( ; pindex ; pindex = pindex - > GetNextInMainChain ( ) )
for ( ; pindex ; pindex = chainActive . Next ( pindex ) )
{
{
vHeaders . push_back ( pindex - > GetBlockHeader ( ) ) ;
vHeaders . push_back ( pindex - > GetBlockHeader ( ) ) ;
if ( - - nLimit < = 0 | | pindex - > GetBlockHash ( ) = = hashStop )
if ( - - nLimit < = 0 | | pindex - > GetBlockHash ( ) = = hashStop )
@ -4097,7 +4096,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
// Start block sync
// Start block sync
if ( pto - > fStartSync & & ! fImporting & & ! fReindex ) {
if ( pto - > fStartSync & & ! fImporting & & ! fReindex ) {
pto - > fStartSync = false ;
pto - > fStartSync = false ;
PushGetBlocks ( pto , pindexBest , uint256 ( 0 ) ) ;
PushGetBlocks ( pto , chainActive . Tip ( ) , uint256 ( 0 ) ) ;
}
}
// Resend wallet transactions that haven't gotten in a block yet
// Resend wallet transactions that haven't gotten in a block yet