|
|
@ -2079,47 +2079,43 @@ static CBlockIndex* FindMostWorkChain() { |
|
|
|
} while(true); |
|
|
|
} while(true); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Try to activate to the most-work chain (thereby connecting it).
|
|
|
|
// Try to make some progress towards making pindexMostWork the active block.
|
|
|
|
bool ActivateBestChain(CValidationState &state) { |
|
|
|
static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMostWork) { |
|
|
|
LOCK(cs_main); |
|
|
|
AssertLockHeld(cs_main); |
|
|
|
CBlockIndex *pindexOldTip = chainActive.Tip(); |
|
|
|
CBlockIndex *pindexOldTip = chainActive.Tip(); |
|
|
|
bool fComplete = false; |
|
|
|
CBlockIndex *pindexFork = chainActive.FindFork(pindexMostWork); |
|
|
|
while (!fComplete) { |
|
|
|
|
|
|
|
CBlockIndex *pindexMostWork = FindMostWorkChain(); |
|
|
|
|
|
|
|
CBlockIndex *pindexFork = chainActive.FindFork(pindexMostWork); |
|
|
|
|
|
|
|
fComplete = true; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Check whether we have something to do.
|
|
|
|
|
|
|
|
if (pindexMostWork == NULL) break; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Disconnect active blocks which are no longer in the best chain.
|
|
|
|
// Disconnect active blocks which are no longer in the best chain.
|
|
|
|
while (chainActive.Tip() && chainActive.Tip() != pindexFork) { |
|
|
|
while (chainActive.Tip() && chainActive.Tip() != pindexFork) { |
|
|
|
if (!DisconnectTip(state)) |
|
|
|
if (!DisconnectTip(state)) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Build list of new blocks to connect.
|
|
|
|
// Build list of new blocks to connect.
|
|
|
|
std::vector<CBlockIndex*> vpindexToConnect; |
|
|
|
std::vector<CBlockIndex*> vpindexToConnect; |
|
|
|
vpindexToConnect.reserve(pindexMostWork->nHeight - (pindexFork ? pindexFork->nHeight : -1)); |
|
|
|
vpindexToConnect.reserve(pindexMostWork->nHeight - (pindexFork ? pindexFork->nHeight : -1)); |
|
|
|
while (pindexMostWork && pindexMostWork != pindexFork) { |
|
|
|
while (pindexMostWork && pindexMostWork != pindexFork) { |
|
|
|
vpindexToConnect.push_back(pindexMostWork); |
|
|
|
vpindexToConnect.push_back(pindexMostWork); |
|
|
|
pindexMostWork = pindexMostWork->pprev; |
|
|
|
pindexMostWork = pindexMostWork->pprev; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Connect new blocks.
|
|
|
|
// Connect new blocks.
|
|
|
|
BOOST_REVERSE_FOREACH(CBlockIndex *pindexConnect, vpindexToConnect) { |
|
|
|
BOOST_REVERSE_FOREACH(CBlockIndex *pindexConnect, vpindexToConnect) { |
|
|
|
if (!ConnectTip(state, pindexConnect)) { |
|
|
|
if (!ConnectTip(state, pindexConnect)) { |
|
|
|
if (state.IsInvalid()) { |
|
|
|
if (state.IsInvalid()) { |
|
|
|
// The block violates a consensus rule.
|
|
|
|
// The block violates a consensus rule.
|
|
|
|
if (!state.CorruptionPossible()) |
|
|
|
if (!state.CorruptionPossible()) |
|
|
|
InvalidChainFound(vpindexToConnect.back()); |
|
|
|
InvalidChainFound(vpindexToConnect.back()); |
|
|
|
fComplete = false; |
|
|
|
state = CValidationState(); |
|
|
|
state = CValidationState(); |
|
|
|
break; |
|
|
|
break; |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
// A system error occurred (disk space, database error, ...).
|
|
|
|
// A system error occurred (disk space, database error, ...).
|
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
|
|
|
|
if (!pindexOldTip || chainActive.Tip()->nChainWork > pindexOldTip->nChainWork) { |
|
|
|
|
|
|
|
// We're in a better position than we were. Return temporarily to release the lock.
|
|
|
|
|
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -2136,6 +2132,28 @@ bool ActivateBestChain(CValidationState &state) { |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool ActivateBestChain(CValidationState &state) { |
|
|
|
|
|
|
|
do { |
|
|
|
|
|
|
|
boost::this_thread::interruption_point(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LOCK(cs_main); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Check whether we're done (this could be avoided after the first run,
|
|
|
|
|
|
|
|
// but that's not worth optimizing.
|
|
|
|
|
|
|
|
CBlockIndex *pindexMostWork = FindMostWorkChain(); |
|
|
|
|
|
|
|
if (pindexMostWork == NULL || pindexMostWork == chainActive.Tip()) |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!ActivateBestChainStep(state, pindexMostWork)) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Check whether we're done now.
|
|
|
|
|
|
|
|
if (pindexMostWork == chainActive.Tip()) |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} while(true); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
CBlockIndex* AddToBlockIndex(CBlockHeader& block) |
|
|
|
CBlockIndex* AddToBlockIndex(CBlockHeader& block) |
|
|
|
{ |
|
|
|
{ |
|
|
|