Changeset View
Changeset View
Standalone View
Standalone View
src/validation.cpp
Show First 20 Lines • Show All 2,238 Lines • ▼ Show 20 Lines | LogPrint(BCLog::BENCH, | ||||
nTimeVerify * 0.000001); | nTimeVerify * 0.000001); | ||||
if (fJustCheck) { | if (fJustCheck) { | ||||
return true; | return true; | ||||
} | } | ||||
// Write undo information to disk | // Write undo information to disk | ||||
if (pindex->GetUndoPos().IsNull() || | if (pindex->GetUndoPos().IsNull() || | ||||
!pindex->IsValid(BLOCK_VALID_SCRIPTS)) { | !pindex->IsValid(BlockValidity::SCRIPTS)) { | ||||
if (pindex->GetUndoPos().IsNull()) { | if (pindex->GetUndoPos().IsNull()) { | ||||
CDiskBlockPos _pos; | CDiskBlockPos _pos; | ||||
if (!FindUndoPos( | if (!FindUndoPos( | ||||
state, pindex->nFile, _pos, | state, pindex->nFile, _pos, | ||||
::GetSerializeSize(blockundo, SER_DISK, CLIENT_VERSION) + | ::GetSerializeSize(blockundo, SER_DISK, CLIENT_VERSION) + | ||||
40)) { | 40)) { | ||||
return error("ConnectBlock(): FindUndoPos failed"); | return error("ConnectBlock(): FindUndoPos failed"); | ||||
} | } | ||||
if (!UndoWriteToDisk(blockundo, _pos, pindex->pprev->GetBlockHash(), | if (!UndoWriteToDisk(blockundo, _pos, pindex->pprev->GetBlockHash(), | ||||
config.GetChainParams().DiskMagic())) { | config.GetChainParams().DiskMagic())) { | ||||
return AbortNode(state, "Failed to write undo data"); | return AbortNode(state, "Failed to write undo data"); | ||||
} | } | ||||
// update nUndoPos in block index | // update nUndoPos in block index | ||||
pindex->nUndoPos = _pos.nPos; | pindex->nUndoPos = _pos.nPos; | ||||
pindex->nStatus |= BLOCK_HAVE_UNDO; | pindex->nStatus |= BLOCK_HAVE_UNDO; | ||||
} | } | ||||
pindex->RaiseValidity(BLOCK_VALID_SCRIPTS); | pindex->RaiseValidity(BlockValidity::SCRIPTS); | ||||
setDirtyBlockIndex.insert(pindex); | setDirtyBlockIndex.insert(pindex); | ||||
} | } | ||||
if (fTxIndex && !pblocktree->WriteTxIndex(vPos)) { | if (fTxIndex && !pblocktree->WriteTxIndex(vPos)) { | ||||
return AbortNode(state, "Failed to write transaction index"); | return AbortNode(state, "Failed to write transaction index"); | ||||
} | } | ||||
// add this block to the view's block chain | // add this block to the view's block chain | ||||
▲ Show 20 Lines • Show All 826 Lines • ▼ Show 20 Lines | bool PreciousBlock(const Config &config, CValidationState &state, | ||||
nLastPreciousChainwork = chainActive.Tip()->nChainWork; | nLastPreciousChainwork = chainActive.Tip()->nChainWork; | ||||
setBlockIndexCandidates.erase(pindex); | setBlockIndexCandidates.erase(pindex); | ||||
pindex->nSequenceId = nBlockReverseSequenceId; | pindex->nSequenceId = nBlockReverseSequenceId; | ||||
if (nBlockReverseSequenceId > std::numeric_limits<int32_t>::min()) { | if (nBlockReverseSequenceId > std::numeric_limits<int32_t>::min()) { | ||||
// We can't keep reducing the counter if somebody really wants to | // We can't keep reducing the counter if somebody really wants to | ||||
// call preciousblock 2**31-1 times on the same set of tips... | // call preciousblock 2**31-1 times on the same set of tips... | ||||
nBlockReverseSequenceId--; | nBlockReverseSequenceId--; | ||||
} | } | ||||
if (pindex->IsValid(BLOCK_VALID_TRANSACTIONS) && pindex->nChainTx) { | if (pindex->IsValid(BlockValidity::TRANSACTIONS) && pindex->nChainTx) { | ||||
setBlockIndexCandidates.insert(pindex); | setBlockIndexCandidates.insert(pindex); | ||||
PruneBlockIndexCandidates(); | PruneBlockIndexCandidates(); | ||||
} | } | ||||
} | } | ||||
return ActivateBestChain(config, state); | return ActivateBestChain(config, state); | ||||
} | } | ||||
Show All 25 Lines | bool InvalidateBlock(const Config &config, CValidationState &state, | ||||
// 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. | ||||
UpdateMempoolForReorg(config, disconnectpool, true); | UpdateMempoolForReorg(config, disconnectpool, 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. | ||||
BlockMap::iterator it = mapBlockIndex.begin(); | BlockMap::iterator it = mapBlockIndex.begin(); | ||||
while (it != mapBlockIndex.end()) { | while (it != mapBlockIndex.end()) { | ||||
if (it->second->IsValid(BLOCK_VALID_TRANSACTIONS) && | if (it->second->IsValid(BlockValidity::TRANSACTIONS) && | ||||
it->second->nChainTx && | it->second->nChainTx && | ||||
!setBlockIndexCandidates.value_comp()(it->second, | !setBlockIndexCandidates.value_comp()(it->second, | ||||
chainActive.Tip())) { | chainActive.Tip())) { | ||||
setBlockIndexCandidates.insert(it->second); | setBlockIndexCandidates.insert(it->second); | ||||
} | } | ||||
it++; | it++; | ||||
} | } | ||||
Show All 9 Lines | bool ResetBlockFailureFlags(CBlockIndex *pindex) { | ||||
// Remove the invalidity flag from this block and all its descendants. | // Remove the invalidity flag from this block and all its descendants. | ||||
BlockMap::iterator it = mapBlockIndex.begin(); | BlockMap::iterator it = mapBlockIndex.begin(); | ||||
while (it != mapBlockIndex.end()) { | while (it != mapBlockIndex.end()) { | ||||
if (!it->second->IsValid() && | if (!it->second->IsValid() && | ||||
it->second->GetAncestor(nHeight) == pindex) { | it->second->GetAncestor(nHeight) == pindex) { | ||||
it->second->nStatus &= ~BLOCK_FAILED_MASK; | it->second->nStatus &= ~BLOCK_FAILED_MASK; | ||||
setDirtyBlockIndex.insert(it->second); | setDirtyBlockIndex.insert(it->second); | ||||
if (it->second->IsValid(BLOCK_VALID_TRANSACTIONS) && | if (it->second->IsValid(BlockValidity::TRANSACTIONS) && | ||||
it->second->nChainTx && | it->second->nChainTx && | ||||
setBlockIndexCandidates.value_comp()(chainActive.Tip(), | setBlockIndexCandidates.value_comp()(chainActive.Tip(), | ||||
it->second)) { | it->second)) { | ||||
setBlockIndexCandidates.insert(it->second); | setBlockIndexCandidates.insert(it->second); | ||||
} | } | ||||
if (it->second == pindexBestInvalid) { | if (it->second == pindexBestInvalid) { | ||||
// Reset invalid block marker if it was pointing to one of | // Reset invalid block marker if it was pointing to one of | ||||
// those. | // those. | ||||
Show All 38 Lines | static CBlockIndex *AddToBlockIndex(const CBlockHeader &block) { | ||||
} | } | ||||
pindexNew->nTimeMax = | pindexNew->nTimeMax = | ||||
(pindexNew->pprev | (pindexNew->pprev | ||||
? std::max(pindexNew->pprev->nTimeMax, pindexNew->nTime) | ? std::max(pindexNew->pprev->nTimeMax, pindexNew->nTime) | ||||
: pindexNew->nTime); | : pindexNew->nTime); | ||||
pindexNew->nChainWork = | pindexNew->nChainWork = | ||||
(pindexNew->pprev ? pindexNew->pprev->nChainWork : 0) + | (pindexNew->pprev ? pindexNew->pprev->nChainWork : 0) + | ||||
GetBlockProof(*pindexNew); | GetBlockProof(*pindexNew); | ||||
pindexNew->RaiseValidity(BLOCK_VALID_TREE); | pindexNew->RaiseValidity(BlockValidity::TREE); | ||||
if (pindexBestHeader == nullptr || | if (pindexBestHeader == nullptr || | ||||
pindexBestHeader->nChainWork < pindexNew->nChainWork) { | pindexBestHeader->nChainWork < pindexNew->nChainWork) { | ||||
pindexBestHeader = pindexNew; | pindexBestHeader = pindexNew; | ||||
} | } | ||||
setDirtyBlockIndex.insert(pindexNew); | setDirtyBlockIndex.insert(pindexNew); | ||||
return pindexNew; | return pindexNew; | ||||
} | } | ||||
/** | /** | ||||
* Mark a block as having its data received and checked (up to | * Mark a block as having its data received and checked (up to | ||||
* BLOCK_VALID_TRANSACTIONS). | * BLOCK_VALID_TRANSACTIONS). | ||||
*/ | */ | ||||
bool ReceivedBlockTransactions(const CBlock &block, CValidationState &state, | bool ReceivedBlockTransactions(const CBlock &block, CValidationState &state, | ||||
CBlockIndex *pindexNew, | CBlockIndex *pindexNew, | ||||
const CDiskBlockPos &pos) { | const CDiskBlockPos &pos) { | ||||
pindexNew->nTx = block.vtx.size(); | pindexNew->nTx = block.vtx.size(); | ||||
pindexNew->nChainTx = 0; | pindexNew->nChainTx = 0; | ||||
pindexNew->nFile = pos.nFile; | pindexNew->nFile = pos.nFile; | ||||
pindexNew->nDataPos = pos.nPos; | pindexNew->nDataPos = pos.nPos; | ||||
pindexNew->nUndoPos = 0; | pindexNew->nUndoPos = 0; | ||||
pindexNew->nStatus |= BLOCK_HAVE_DATA; | pindexNew->nStatus |= BLOCK_HAVE_DATA; | ||||
pindexNew->RaiseValidity(BLOCK_VALID_TRANSACTIONS); | pindexNew->RaiseValidity(BlockValidity::TRANSACTIONS); | ||||
setDirtyBlockIndex.insert(pindexNew); | setDirtyBlockIndex.insert(pindexNew); | ||||
if (pindexNew->pprev == nullptr || pindexNew->pprev->nChainTx) { | if (pindexNew->pprev == nullptr || pindexNew->pprev->nChainTx) { | ||||
// If pindexNew is the genesis block or all parents are | // If pindexNew is the genesis block or all parents are | ||||
// BLOCK_VALID_TRANSACTIONS. | // BLOCK_VALID_TRANSACTIONS. | ||||
std::deque<CBlockIndex *> queue; | std::deque<CBlockIndex *> queue; | ||||
queue.push_back(pindexNew); | queue.push_back(pindexNew); | ||||
Show All 20 Lines | if (pindexNew->pprev == nullptr || pindexNew->pprev->nChainTx) { | ||||
std::multimap<CBlockIndex *, CBlockIndex *>::iterator it = | std::multimap<CBlockIndex *, CBlockIndex *>::iterator it = | ||||
range.first; | range.first; | ||||
queue.push_back(it->second); | queue.push_back(it->second); | ||||
range.first++; | range.first++; | ||||
mapBlocksUnlinked.erase(it); | mapBlocksUnlinked.erase(it); | ||||
} | } | ||||
} | } | ||||
} else { | } else { | ||||
if (pindexNew->pprev && pindexNew->pprev->IsValid(BLOCK_VALID_TREE)) { | if (pindexNew->pprev && | ||||
pindexNew->pprev->IsValid(BlockValidity::TREE)) { | |||||
mapBlocksUnlinked.insert( | mapBlocksUnlinked.insert( | ||||
std::make_pair(pindexNew->pprev, pindexNew)); | std::make_pair(pindexNew->pprev, pindexNew)); | ||||
} | } | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 994 Lines • ▼ Show 20 Lines | for (const std::pair<int, CBlockIndex *> &item : vSortedByHeight) { | ||||
pindex->nChainTx = 0; | pindex->nChainTx = 0; | ||||
mapBlocksUnlinked.insert( | mapBlocksUnlinked.insert( | ||||
std::make_pair(pindex->pprev, pindex)); | std::make_pair(pindex->pprev, pindex)); | ||||
} | } | ||||
} else { | } else { | ||||
pindex->nChainTx = pindex->nTx; | pindex->nChainTx = pindex->nTx; | ||||
} | } | ||||
} | } | ||||
if (pindex->IsValid(BLOCK_VALID_TRANSACTIONS) && | if (pindex->IsValid(BlockValidity::TRANSACTIONS) && | ||||
(pindex->nChainTx || pindex->pprev == nullptr)) { | (pindex->nChainTx || pindex->pprev == nullptr)) { | ||||
setBlockIndexCandidates.insert(pindex); | setBlockIndexCandidates.insert(pindex); | ||||
} | } | ||||
if (pindex->nStatus & BLOCK_FAILED_MASK && | if (pindex->nStatus & BLOCK_FAILED_MASK && | ||||
(!pindexBestInvalid || | (!pindexBestInvalid || | ||||
pindex->nChainWork > pindexBestInvalid->nChainWork)) { | pindex->nChainWork > pindexBestInvalid->nChainWork)) { | ||||
pindexBestInvalid = pindex; | pindexBestInvalid = pindex; | ||||
} | } | ||||
if (pindex->pprev) { | if (pindex->pprev) { | ||||
pindex->BuildSkip(); | pindex->BuildSkip(); | ||||
} | } | ||||
if (pindex->IsValid(BLOCK_VALID_TREE) && | if (pindex->IsValid(BlockValidity::TREE) && | ||||
(pindexBestHeader == nullptr || | (pindexBestHeader == nullptr || | ||||
CBlockIndexWorkComparator()(pindexBestHeader, pindex))) { | CBlockIndexWorkComparator()(pindexBestHeader, pindex))) { | ||||
pindexBestHeader = pindex; | pindexBestHeader = pindex; | ||||
} | } | ||||
} | } | ||||
// Load block file info | // Load block file info | ||||
pblocktree->ReadLastBlockFile(nLastBlockFile); | pblocktree->ReadLastBlockFile(nLastBlockFile); | ||||
▲ Show 20 Lines • Show All 387 Lines • ▼ Show 20 Lines | bool RewindBlockIndex(const Config &config) { | ||||
// Reduce validity flag and have-data flags. | // Reduce validity flag and have-data flags. | ||||
// We do this after actual disconnecting, otherwise we'll end up writing the | // We do this after actual disconnecting, otherwise we'll end up writing the | ||||
// lack of data to disk before writing the chainstate, resulting in a | // lack of data to disk before writing the chainstate, resulting in a | ||||
// failure to continue if interrupted. | // failure to continue if interrupted. | ||||
for (BlockMap::iterator it = mapBlockIndex.begin(); | for (BlockMap::iterator it = mapBlockIndex.begin(); | ||||
it != mapBlockIndex.end(); it++) { | it != mapBlockIndex.end(); it++) { | ||||
CBlockIndex *pindexIter = it->second; | CBlockIndex *pindexIter = it->second; | ||||
if (pindexIter->IsValid(BLOCK_VALID_TRANSACTIONS) && | if (pindexIter->IsValid(BlockValidity::TRANSACTIONS) && | ||||
pindexIter->nChainTx) { | pindexIter->nChainTx) { | ||||
setBlockIndexCandidates.insert(pindexIter); | setBlockIndexCandidates.insert(pindexIter); | ||||
} | } | ||||
} | } | ||||
PruneBlockIndexCandidates(); | PruneBlockIndexCandidates(); | ||||
CheckBlockIndex(params.GetConsensus()); | CheckBlockIndex(params.GetConsensus()); | ||||
▲ Show 20 Lines • Show All 728 Lines • Show Last 20 Lines |