Changeset View
Changeset View
Standalone View
Standalone View
src/validation.cpp
Show First 20 Lines • Show All 117 Lines • ▼ Show 20 Lines | private: | ||||
* descendants. Since this case should be very rare, keeping track of all | * descendants. Since this case should be very rare, keeping track of all | ||||
* BLOCK_FAILED_VALID blocks in a set should be just fine and work just as | * BLOCK_FAILED_VALID blocks in a set should be just fine and work just as | ||||
* well. | * well. | ||||
* | * | ||||
* Because we already walk mapBlockIndex in height-order at startup, we go | * Because we already walk mapBlockIndex in height-order at startup, we go | ||||
* ahead and mark descendants of invalid blocks as FAILED_CHILD at that | * ahead and mark descendants of invalid blocks as FAILED_CHILD at that | ||||
* time, instead of putting things in this set. | * time, instead of putting things in this set. | ||||
*/ | */ | ||||
std::set<CBlockIndex *> g_failed_blocks; | std::set<CBlockIndex *> m_failed_blocks; | ||||
public: | public: | ||||
CChain chainActive; | CChain chainActive; | ||||
BlockMap mapBlockIndex; | BlockMap mapBlockIndex; | ||||
std::multimap<CBlockIndex *, CBlockIndex *> mapBlocksUnlinked; | std::multimap<CBlockIndex *, CBlockIndex *> mapBlocksUnlinked; | ||||
CBlockIndex *pindexBestInvalid = nullptr; | CBlockIndex *pindexBestInvalid = nullptr; | ||||
CBlockIndex *pindexBestParked = nullptr; | CBlockIndex *pindexBestParked = nullptr; | ||||
▲ Show 20 Lines • Show All 1,000 Lines • ▼ Show 20 Lines | LogPrintf("%s: current best=%s height=%d log2_work=%.8g date=%s\n", | ||||
log(tip->nChainWork.getdouble()) / log(2.0), | log(tip->nChainWork.getdouble()) / log(2.0), | ||||
FormatISO8601DateTime(tip->GetBlockTime())); | FormatISO8601DateTime(tip->GetBlockTime())); | ||||
} | } | ||||
void CChainState::InvalidBlockFound(CBlockIndex *pindex, | void CChainState::InvalidBlockFound(CBlockIndex *pindex, | ||||
const CValidationState &state) { | const CValidationState &state) { | ||||
if (!state.CorruptionPossible()) { | if (!state.CorruptionPossible()) { | ||||
pindex->nStatus = pindex->nStatus.withFailed(); | pindex->nStatus = pindex->nStatus.withFailed(); | ||||
g_failed_blocks.insert(pindex); | m_failed_blocks.insert(pindex); | ||||
setDirtyBlockIndex.insert(pindex); | setDirtyBlockIndex.insert(pindex); | ||||
InvalidChainFound(pindex); | InvalidChainFound(pindex); | ||||
} | } | ||||
} | } | ||||
void SpendCoins(CCoinsViewCache &view, const CTransaction &tx, CTxUndo &txundo, | void SpendCoins(CCoinsViewCache &view, const CTransaction &tx, CTxUndo &txundo, | ||||
int nHeight) { | int nHeight) { | ||||
// Mark inputs spent. | // Mark inputs spent. | ||||
▲ Show 20 Lines • Show All 1,850 Lines • ▼ Show 20 Lines | while (pindex_was_in_chain && invalid_walk_tip != pindex) { | ||||
invalid_walk_tip = invalid_walk_tip->pprev; | invalid_walk_tip = invalid_walk_tip->pprev; | ||||
} | } | ||||
// Mark the block as either invalid or parked. | // Mark the block as either invalid or parked. | ||||
pindex->nStatus = invalidate ? pindex->nStatus.withFailed() | pindex->nStatus = invalidate ? pindex->nStatus.withFailed() | ||||
: pindex->nStatus.withParked(); | : pindex->nStatus.withParked(); | ||||
setDirtyBlockIndex.insert(pindex); | setDirtyBlockIndex.insert(pindex); | ||||
if (invalidate) { | if (invalidate) { | ||||
g_failed_blocks.insert(pindex); | m_failed_blocks.insert(pindex); | ||||
} | } | ||||
// DisconnectTip will add transactions to disconnectpool; try to add these | // DisconnectTip will add transactions to disconnectpool; try to add these | ||||
// back to the mempool. | // back to the mempool. | ||||
disconnectpool.updateMempoolForReorg(config, true); | disconnectpool.updateMempoolForReorg(config, true); | ||||
// The resulting new best tip may not be in setBlockIndexCandidates anymore, | // The resulting new best tip may not be in setBlockIndexCandidates anymore, | ||||
// so add it again. | // so add it again. | ||||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | |||||
void CChainState::UpdateFlagsForBlock(CBlockIndex *pindexBase, | void CChainState::UpdateFlagsForBlock(CBlockIndex *pindexBase, | ||||
CBlockIndex *pindex, F f) { | CBlockIndex *pindex, F f) { | ||||
BlockStatus newStatus = f(pindex->nStatus); | BlockStatus newStatus = f(pindex->nStatus); | ||||
if (pindex->nStatus != newStatus && | if (pindex->nStatus != newStatus && | ||||
pindex->GetAncestor(pindexBase->nHeight) == pindexBase) { | pindex->GetAncestor(pindexBase->nHeight) == pindexBase) { | ||||
pindex->nStatus = newStatus; | pindex->nStatus = newStatus; | ||||
setDirtyBlockIndex.insert(pindex); | setDirtyBlockIndex.insert(pindex); | ||||
if (newStatus.isValid()) { | if (newStatus.isValid()) { | ||||
g_failed_blocks.erase(pindex); | m_failed_blocks.erase(pindex); | ||||
} | } | ||||
if (pindex->IsValid(BlockValidity::TRANSACTIONS) && pindex->nChainTx && | if (pindex->IsValid(BlockValidity::TRANSACTIONS) && pindex->nChainTx && | ||||
setBlockIndexCandidates.value_comp()(chainActive.Tip(), pindex)) { | setBlockIndexCandidates.value_comp()(chainActive.Tip(), pindex)) { | ||||
setBlockIndexCandidates.insert(pindex); | setBlockIndexCandidates.insert(pindex); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
Show All 14 Lines | void CChainState::UpdateFlags(CBlockIndex *pindex, F f, C fchild) { | ||||
// Update the flags from all ancestors too. | // Update the flags from all ancestors too. | ||||
while (pindex != nullptr) { | while (pindex != nullptr) { | ||||
BlockStatus newStatus = f(pindex->nStatus); | BlockStatus newStatus = f(pindex->nStatus); | ||||
if (pindex->nStatus != newStatus) { | if (pindex->nStatus != newStatus) { | ||||
pindex->nStatus = newStatus; | pindex->nStatus = newStatus; | ||||
setDirtyBlockIndex.insert(pindex); | setDirtyBlockIndex.insert(pindex); | ||||
if (newStatus.isValid()) { | if (newStatus.isValid()) { | ||||
g_failed_blocks.erase(pindex); | m_failed_blocks.erase(pindex); | ||||
} | } | ||||
} | } | ||||
pindex = pindex->pprev; | pindex = pindex->pprev; | ||||
} | } | ||||
} | } | ||||
template <typename F> void CChainState::UpdateFlags(CBlockIndex *pindex, F f) { | template <typename F> void CChainState::UpdateFlags(CBlockIndex *pindex, F f) { | ||||
// Handy shorthand. | // Handy shorthand. | ||||
▲ Show 20 Lines • Show All 637 Lines • ▼ Show 20 Lines | if (hash != chainparams.GetConsensus().hashGenesisBlock) { | ||||
if (!ContextualCheckBlockHeader(config, block, state, pindexPrev, | if (!ContextualCheckBlockHeader(config, block, state, pindexPrev, | ||||
GetAdjustedTime())) { | GetAdjustedTime())) { | ||||
return error("%s: Consensus::ContextualCheckBlockHeader: %s, %s", | return error("%s: Consensus::ContextualCheckBlockHeader: %s, %s", | ||||
__func__, hash.ToString(), FormatStateMessage(state)); | __func__, hash.ToString(), FormatStateMessage(state)); | ||||
} | } | ||||
if (!pindexPrev->IsValid(BlockValidity::SCRIPTS)) { | if (!pindexPrev->IsValid(BlockValidity::SCRIPTS)) { | ||||
for (const CBlockIndex *failedit : g_failed_blocks) { | for (const CBlockIndex *failedit : m_failed_blocks) { | ||||
if (pindexPrev->GetAncestor(failedit->nHeight) == failedit) { | if (pindexPrev->GetAncestor(failedit->nHeight) == failedit) { | ||||
assert(failedit->nStatus.hasFailed()); | assert(failedit->nStatus.hasFailed()); | ||||
CBlockIndex *invalid_walk = pindexPrev; | CBlockIndex *invalid_walk = pindexPrev; | ||||
while (invalid_walk != failedit) { | while (invalid_walk != failedit) { | ||||
invalid_walk->nStatus = | invalid_walk->nStatus = | ||||
invalid_walk->nStatus.withFailedParent(); | invalid_walk->nStatus.withFailedParent(); | ||||
setDirtyBlockIndex.insert(invalid_walk); | setDirtyBlockIndex.insert(invalid_walk); | ||||
invalid_walk = invalid_walk->pprev; | invalid_walk = invalid_walk->pprev; | ||||
▲ Show 20 Lines • Show All 1,088 Lines • ▼ Show 20 Lines | bool RewindBlockIndex(const Config &config) { | ||||
return true; | return true; | ||||
} | } | ||||
// May NOT be used after any connections are up as much of the peer-processing | // May NOT be used after any connections are up as much of the peer-processing | ||||
// logic assumes a consistent block index state | // logic assumes a consistent block index state | ||||
void CChainState::UnloadBlockIndex() { | void CChainState::UnloadBlockIndex() { | ||||
nBlockSequenceId = 1; | nBlockSequenceId = 1; | ||||
g_failed_blocks.clear(); | m_failed_blocks.clear(); | ||||
setBlockIndexCandidates.clear(); | setBlockIndexCandidates.clear(); | ||||
} | } | ||||
// May NOT be used after any connections are up as much | // May NOT be used after any connections are up as much | ||||
// of the peer-processing logic assumes a consistent | // of the peer-processing logic assumes a consistent | ||||
// block index state | // block index state | ||||
void UnloadBlockIndex() { | void UnloadBlockIndex() { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
▲ Show 20 Lines • Show All 752 Lines • Show Last 20 Lines |