MCPcopy Create free account
hub / github.com/bitcoin/bitcoin / FindMostWorkChain

Method FindMostWorkChain

src/validation.cpp:3128–3181  ·  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

3126 * known to be invalid (it's however far from certain to be valid).
3127 */
3128CBlockIndex* Chainstate::FindMostWorkChain()
3129{
3130 AssertLockHeld(::cs_main);
3131 do {
3132 CBlockIndex *pindexNew = nullptr;
3133
3134 // Find the best candidate header.
3135 {
3136 std::set<CBlockIndex*, CBlockIndexWorkComparator>::reverse_iterator it = setBlockIndexCandidates.rbegin();
3137 if (it == setBlockIndexCandidates.rend())
3138 return nullptr;
3139 pindexNew = *it;
3140 }
3141
3142 // Check whether all blocks on the path between the currently active chain and the candidate are valid.
3143 // Just going until the active chain is an optimization, as we know all blocks in it are valid already.
3144 bool fInvalidAncestor = false;
3145 for (CBlockIndex *pindexTest = pindexNew; pindexTest && !m_chain.Contains(*pindexTest); pindexTest = pindexTest->pprev) {
3146 assert(pindexTest->HaveNumChainTxs() || pindexTest->nHeight == 0);
3147
3148 // Pruned nodes may have entries in setBlockIndexCandidates for
3149 // which block files have been deleted. Remove those as candidates
3150 // for the most work chain if we come across them; we can't switch
3151 // to a chain unless we have all the non-active-chain parent blocks.
3152 bool fFailedChain = pindexTest->nStatus & BLOCK_FAILED_VALID;
3153 bool fMissingData = !(pindexTest->nStatus & BLOCK_HAVE_DATA);
3154 if (fFailedChain || fMissingData) {
3155 // Candidate chain is not usable (either invalid or missing data)
3156 if (fFailedChain && (m_chainman.m_best_invalid == nullptr || pindexNew->nChainWork > m_chainman.m_best_invalid->nChainWork)) {
3157 m_chainman.m_best_invalid = pindexNew;
3158 }
3159 // Remove the entire chain from the set.
3160 for (CBlockIndex *pindexFailed = pindexNew; pindexFailed != pindexTest; pindexFailed = pindexFailed->pprev) {
3161 // If we're missing data and not a descendant of an invalid block,
3162 // then add back to m_blocks_unlinked, so that if the block arrives in the future
3163 // we can try adding to setBlockIndexCandidates again.
3164 if (fMissingData && !fFailedChain) {
3165 // Avoid duplicate entries in m_blocks_unlinked. If the same entry is
3166 // processed twice in ReceivedBlockTransactions(), it may be re-added to
3167 // setBlockIndexCandidates with a modified nSequenceId, breaking ordering
3168 // guarantees and leading to undefined behavior.
3169 m_blockman.AddUnlinkedBlock(pindexFailed);
3170 }
3171 setBlockIndexCandidates.erase(pindexFailed);
3172 }
3173 setBlockIndexCandidates.erase(pindexTest);
3174 fInvalidAncestor = true;
3175 break;
3176 }
3177 }
3178 if (!fInvalidAncestor)
3179 return pindexNew;
3180 } while(true);
3181}
3182
3183/** Delete all entries in setBlockIndexCandidates that are worse than the current tip. */
3184void Chainstate::PruneBlockIndexCandidates() {

Callers

nothing calls this directly

Calls 6

rbeginMethod · 0.80
rendMethod · 0.80
HaveNumChainTxsMethod · 0.80
AddUnlinkedBlockMethod · 0.80
ContainsMethod · 0.45
eraseMethod · 0.45

Tested by

no test coverage detected