MCPcopy Create free account
hub / github.com/ElementsProject/elements / FindMostWorkChain

Method FindMostWorkChain

src/validation.cpp:2987–3043  ·  view source on GitHub ↗

* Return the tip of the chain with the most work in it, that isn't * known to be invalid (it's however far from certain to be valid). */

Source from the content-addressed store, hash-verified

2985 * known to be invalid (it's however far from certain to be valid).
2986 */
2987CBlockIndex* CChainState::FindMostWorkChain()
2988{
2989 AssertLockHeld(::cs_main);
2990 do {
2991 CBlockIndex *pindexNew = nullptr;
2992
2993 // Find the best candidate header.
2994 {
2995 std::set<CBlockIndex*, CBlockIndexWorkComparator>::reverse_iterator it = setBlockIndexCandidates.rbegin();
2996 if (it == setBlockIndexCandidates.rend())
2997 return nullptr;
2998 pindexNew = *it;
2999 }
3000
3001 // Check whether all blocks on the path between the currently active chain and the candidate are valid.
3002 // Just going until the active chain is an optimization, as we know all blocks in it are valid already.
3003 CBlockIndex *pindexTest = pindexNew;
3004 bool fInvalidAncestor = false;
3005 while (pindexTest && !m_chain.Contains(pindexTest)) {
3006 assert(pindexTest->HaveTxsDownloaded() || pindexTest->nHeight == 0);
3007
3008 // Pruned nodes may have entries in setBlockIndexCandidates for
3009 // which block files have been deleted. Remove those as candidates
3010 // for the most work chain if we come across them; we can't switch
3011 // to a chain unless we have all the non-active-chain parent blocks.
3012 bool fFailedChain = pindexTest->nStatus & BLOCK_FAILED_MASK;
3013 bool fMissingData = !(pindexTest->nStatus & BLOCK_HAVE_DATA);
3014 if (fFailedChain || fMissingData) {
3015 // Candidate chain is not usable (either invalid or missing data)
3016 if (fFailedChain && (m_chainman.m_best_invalid == nullptr || pindexNew->nChainWork > m_chainman.m_best_invalid->nChainWork)) {
3017 m_chainman.m_best_invalid = pindexNew;
3018 }
3019 CBlockIndex *pindexFailed = pindexNew;
3020 // Remove the entire chain from the set.
3021 while (pindexTest != pindexFailed) {
3022 if (fFailedChain) {
3023 pindexFailed->nStatus |= BLOCK_FAILED_CHILD;
3024 } else if (fMissingData) {
3025 // If we're missing data, then add back to m_blocks_unlinked,
3026 // so that if the block arrives in the future we can try adding
3027 // to setBlockIndexCandidates again.
3028 m_blockman.m_blocks_unlinked.insert(
3029 std::make_pair(pindexFailed->pprev, pindexFailed));
3030 }
3031 setBlockIndexCandidates.erase(pindexFailed);
3032 pindexFailed = pindexFailed->pprev;
3033 }
3034 setBlockIndexCandidates.erase(pindexTest);
3035 fInvalidAncestor = true;
3036 break;
3037 }
3038 pindexTest = pindexTest->pprev;
3039 }
3040 if (!fInvalidAncestor)
3041 return pindexNew;
3042 } while(true);
3043}
3044

Callers

nothing calls this directly

Calls 6

rbeginMethod · 0.80
rendMethod · 0.80
HaveTxsDownloadedMethod · 0.80
ContainsMethod · 0.45
insertMethod · 0.45
eraseMethod · 0.45

Tested by

no test coverage detected