Changeset View
Changeset View
Standalone View
Standalone View
src/validation.cpp
Show First 20 Lines • Show All 168 Lines • ▼ Show 20 Lines | public: | ||||
bool PreciousBlock(const Config &config, CValidationState &state, | bool PreciousBlock(const Config &config, CValidationState &state, | ||||
CBlockIndex *pindex) LOCKS_EXCLUDED(cs_main); | CBlockIndex *pindex) LOCKS_EXCLUDED(cs_main); | ||||
bool UnwindBlock(const Config &config, CValidationState &state, | bool UnwindBlock(const Config &config, CValidationState &state, | ||||
CBlockIndex *pindex, bool invalidate) | CBlockIndex *pindex, bool invalidate) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | EXCLUSIVE_LOCKS_REQUIRED(cs_main); | ||||
void ResetBlockFailureFlags(CBlockIndex *pindex) | void ResetBlockFailureFlags(CBlockIndex *pindex) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | EXCLUSIVE_LOCKS_REQUIRED(cs_main); | ||||
template <typename F> | template <typename F> | ||||
void UpdateFlagsForBlock(CBlockIndex *pindexBase, CBlockIndex *pindex, F f); | void UpdateFlagsForBlock(CBlockIndex *pindexBase, CBlockIndex *pindex, F f) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | |||||
template <typename F, typename C> | template <typename F, typename C> | ||||
void UpdateFlags(CBlockIndex *pindex, F f, C fchild) | void UpdateFlags(CBlockIndex *pindex, F f, C fchild) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | EXCLUSIVE_LOCKS_REQUIRED(cs_main); | ||||
template <typename F> | template <typename F> | ||||
void UpdateFlags(CBlockIndex *pindex, F f) | void UpdateFlags(CBlockIndex *pindex, F f) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | EXCLUSIVE_LOCKS_REQUIRED(cs_main); | ||||
/** Remove parked status from a block and its descendants. */ | /** Remove parked status from a block and its descendants. */ | ||||
void UnparkBlockImpl(CBlockIndex *pindex, bool fClearChildren) | void UnparkBlockImpl(CBlockIndex *pindex, bool fClearChildren) | ||||
▲ Show 20 Lines • Show All 679 Lines • ▼ Show 20 Lines | |||||
/** | /** | ||||
* (try to) add transaction to memory pool with a specified acceptance time. | * (try to) add transaction to memory pool with a specified acceptance time. | ||||
*/ | */ | ||||
static bool AcceptToMemoryPoolWithTime( | static bool AcceptToMemoryPoolWithTime( | ||||
const Config &config, CTxMemPool &pool, CValidationState &state, | const Config &config, CTxMemPool &pool, CValidationState &state, | ||||
const CTransactionRef &tx, bool fLimitFree, bool *pfMissingInputs, | const CTransactionRef &tx, bool fLimitFree, bool *pfMissingInputs, | ||||
int64_t nAcceptTime, bool fOverrideMempoolLimit, const Amount nAbsurdFee, | int64_t nAcceptTime, bool fOverrideMempoolLimit, const Amount nAbsurdFee, | ||||
bool test_accept) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | bool test_accept) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | ||||
AssertLockHeld(cs_main); | |||||
std::vector<COutPoint> coins_to_uncache; | std::vector<COutPoint> coins_to_uncache; | ||||
bool res = AcceptToMemoryPoolWorker( | bool res = AcceptToMemoryPoolWorker( | ||||
config, pool, state, tx, fLimitFree, pfMissingInputs, nAcceptTime, | config, pool, state, tx, fLimitFree, pfMissingInputs, nAcceptTime, | ||||
fOverrideMempoolLimit, nAbsurdFee, coins_to_uncache, test_accept); | fOverrideMempoolLimit, nAbsurdFee, coins_to_uncache, test_accept); | ||||
if (!res) { | if (!res) { | ||||
for (const COutPoint &outpoint : coins_to_uncache) { | for (const COutPoint &outpoint : coins_to_uncache) { | ||||
pcoinsTip->Uncache(outpoint); | pcoinsTip->Uncache(outpoint); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 282 Lines • ▼ Show 20 Lines | if (pfork && | ||||
chainActive.Height() - pindexNewForkTip->nHeight < 72) { | chainActive.Height() - pindexNewForkTip->nHeight < 72) { | ||||
pindexBestForkTip = pindexNewForkTip; | pindexBestForkTip = pindexNewForkTip; | ||||
pindexBestForkBase = pfork; | pindexBestForkBase = pfork; | ||||
} | } | ||||
CheckForkWarningConditions(); | CheckForkWarningConditions(); | ||||
} | } | ||||
void static InvalidChainFound(CBlockIndex *pindexNew) | static void InvalidChainFound(CBlockIndex *pindexNew) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | ||||
AssertLockHeld(cs_main); | |||||
if (!pindexBestInvalid || | if (!pindexBestInvalid || | ||||
pindexNew->nChainWork > pindexBestInvalid->nChainWork) { | pindexNew->nChainWork > pindexBestInvalid->nChainWork) { | ||||
pindexBestInvalid = pindexNew; | pindexBestInvalid = pindexNew; | ||||
} | } | ||||
// If the invalid chain found is supposed to be finalized, we need to move | // If the invalid chain found is supposed to be finalized, we need to move | ||||
// back the finalization point. | // back the finalization point. | ||||
if (IsBlockFinalized(pindexNew)) { | if (IsBlockFinalized(pindexNew)) { | ||||
▲ Show 20 Lines • Show All 71 Lines • ▼ Show 20 Lines | int GetSpendHeight(const CCoinsViewCache &inputs) { | ||||
return pindexPrev->nHeight + 1; | return pindexPrev->nHeight + 1; | ||||
} | } | ||||
bool CheckInputs(const CTransaction &tx, CValidationState &state, | bool CheckInputs(const CTransaction &tx, CValidationState &state, | ||||
const CCoinsViewCache &inputs, bool fScriptChecks, | const CCoinsViewCache &inputs, bool fScriptChecks, | ||||
const uint32_t flags, bool sigCacheStore, | const uint32_t flags, bool sigCacheStore, | ||||
bool scriptCacheStore, | bool scriptCacheStore, | ||||
const PrecomputedTransactionData &txdata, | const PrecomputedTransactionData &txdata, | ||||
std::vector<CScriptCheck> *pvChecks) | std::vector<CScriptCheck> *pvChecks) { | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | AssertLockHeld(cs_main); | ||||
assert(!tx.IsCoinBase()); | assert(!tx.IsCoinBase()); | ||||
if (pvChecks) { | if (pvChecks) { | ||||
pvChecks->reserve(tx.vin.size()); | pvChecks->reserve(tx.vin.size()); | ||||
} | } | ||||
// Skip script verification when connecting blocks under the assumevalid | // Skip script verification when connecting blocks under the assumevalid | ||||
// block. Assuming the assumevalid block is valid this is safe because | // block. Assuming the assumevalid block is valid this is safe because | ||||
▲ Show 20 Lines • Show All 414 Lines • ▼ Show 20 Lines | |||||
* Apply the effects of this block (with given index) on the UTXO set | * Apply the effects of this block (with given index) on the UTXO set | ||||
* represented by coins. Validity checks that depend on the UTXO set are also | * represented by coins. Validity checks that depend on the UTXO set are also | ||||
* done; ConnectBlock() can fail if those validity checks fail (among other | * done; ConnectBlock() can fail if those validity checks fail (among other | ||||
* reasons). | * reasons). | ||||
*/ | */ | ||||
bool CChainState::ConnectBlock(const CBlock &block, CValidationState &state, | bool CChainState::ConnectBlock(const CBlock &block, CValidationState &state, | ||||
CBlockIndex *pindex, CCoinsViewCache &view, | CBlockIndex *pindex, CCoinsViewCache &view, | ||||
const CChainParams ¶ms, | const CChainParams ¶ms, | ||||
BlockValidationOptions options, bool fJustCheck) | BlockValidationOptions options, | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | bool fJustCheck) { | ||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
assert(pindex); | assert(pindex); | ||||
assert(*pindex->phashBlock == block.GetHash()); | assert(*pindex->phashBlock == block.GetHash()); | ||||
int64_t nTimeStart = GetTimeMicros(); | int64_t nTimeStart = GetTimeMicros(); | ||||
const Consensus::Params &consensusParams = params.GetConsensus(); | const Consensus::Params &consensusParams = params.GetConsensus(); | ||||
// Check it again in case a previous version let a bad block in | // Check it again in case a previous version let a bad block in | ||||
▲ Show 20 Lines • Show All 522 Lines • ▼ Show 20 Lines | |||||
* should make the mempool consistent again by calling updateMempoolForReorg. | * should make the mempool consistent again by calling updateMempoolForReorg. | ||||
* with cs_main held. | * with cs_main held. | ||||
* | * | ||||
* If disconnectpool is nullptr, then no disconnected transactions are added to | * If disconnectpool is nullptr, then no disconnected transactions are added to | ||||
* disconnectpool (note that the caller is responsible for mempool consistency | * disconnectpool (note that the caller is responsible for mempool consistency | ||||
* in any case). | * in any case). | ||||
*/ | */ | ||||
bool CChainState::DisconnectTip(const Config &config, CValidationState &state, | bool CChainState::DisconnectTip(const Config &config, CValidationState &state, | ||||
DisconnectedBlockTransactions *disconnectpool) | DisconnectedBlockTransactions *disconnectpool) { | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | AssertLockHeld(cs_main); | ||||
CBlockIndex *pindexDelete = chainActive.Tip(); | CBlockIndex *pindexDelete = chainActive.Tip(); | ||||
const Consensus::Params &consensusParams = | const Consensus::Params &consensusParams = | ||||
config.GetChainParams().GetConsensus(); | config.GetChainParams().GetConsensus(); | ||||
assert(pindexDelete); | assert(pindexDelete); | ||||
// Read block from disk. | // Read block from disk. | ||||
std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>(); | std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>(); | ||||
▲ Show 20 Lines • Show All 889 Lines • ▼ Show 20 Lines | bool CChainState::UnwindBlock(const Config &config, CValidationState &state, | ||||
// Only notify about a new block tip if the active chain was modified. | // Only notify about a new block tip if the active chain was modified. | ||||
if (pindex_was_in_chain) { | if (pindex_was_in_chain) { | ||||
uiInterface.NotifyBlockTip(IsInitialBlockDownload(), pindex->pprev); | uiInterface.NotifyBlockTip(IsInitialBlockDownload(), pindex->pprev); | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
bool FinalizeBlockAndInvalidate(const Config &config, CValidationState &state, | bool FinalizeBlockAndInvalidate(const Config &config, CValidationState &state, | ||||
CBlockIndex *pindex) | CBlockIndex *pindex) { | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | |||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
if (!FinalizeBlockInternal(config, state, pindex)) { | if (!FinalizeBlockInternal(config, state, pindex)) { | ||||
// state is set by FinalizeBlockInternal. | // state is set by FinalizeBlockInternal. | ||||
return false; | return false; | ||||
} | } | ||||
// We have a valid candidate, make sure it is not parked. | // We have a valid candidate, make sure it is not parked. | ||||
if (pindex->nStatus.isOnParkedChain()) { | if (pindex->nStatus.isOnParkedChain()) { | ||||
Show All 36 Lines | if (pindex->nStatus != newStatus && | ||||
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); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
template <typename F, typename C> | template <typename F, typename C> | ||||
void CChainState::UpdateFlags(CBlockIndex *pindex, F f, C fchild) | void CChainState::UpdateFlags(CBlockIndex *pindex, F f, C fchild) { | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | |||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
// Update the current block. | // Update the current block. | ||||
UpdateFlagsForBlock(pindex, pindex, f); | UpdateFlagsForBlock(pindex, pindex, f); | ||||
// Update the flags from this block and all its descendants. | // Update the flags 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()) { | ||||
Show All 10 Lines | while (pindex != nullptr) { | ||||
if (newStatus.isValid()) { | if (newStatus.isValid()) { | ||||
m_failed_blocks.erase(pindex); | m_failed_blocks.erase(pindex); | ||||
} | } | ||||
} | } | ||||
pindex = pindex->pprev; | pindex = pindex->pprev; | ||||
} | } | ||||
} | } | ||||
template <typename F> | template <typename F> void CChainState::UpdateFlags(CBlockIndex *pindex, F f) { | ||||
void CChainState::UpdateFlags(CBlockIndex *pindex, F f) | |||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | |||||
// Handy shorthand. | // Handy shorthand. | ||||
UpdateFlags(pindex, f, f); | UpdateFlags(pindex, f, f); | ||||
} | } | ||||
void CChainState::ResetBlockFailureFlags(CBlockIndex *pindex) { | void CChainState::ResetBlockFailureFlags(CBlockIndex *pindex) { | ||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
if (pindexBestInvalid && | if (pindexBestInvalid && | ||||
▲ Show 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
bool IsBlockFinalized(const CBlockIndex *pindex) { | bool IsBlockFinalized(const CBlockIndex *pindex) { | ||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
return pindexFinalized && | return pindexFinalized && | ||||
pindexFinalized->GetAncestor(pindex->nHeight) == pindex; | pindexFinalized->GetAncestor(pindex->nHeight) == pindex; | ||||
} | } | ||||
CBlockIndex *CChainState::AddToBlockIndex(const CBlockHeader &block) | CBlockIndex *CChainState::AddToBlockIndex(const CBlockHeader &block) { | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | |||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
// Check for duplicate | // Check for duplicate | ||||
BlockHash hash = block.GetHash(); | BlockHash hash = block.GetHash(); | ||||
BlockMap::iterator it = mapBlockIndex.find(hash); | BlockMap::iterator it = mapBlockIndex.find(hash); | ||||
if (it != mapBlockIndex.end()) { | if (it != mapBlockIndex.end()) { | ||||
return it->second; | return it->second; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 1,158 Lines • ▼ Show 20 Lines | CBlockIndex *CChainState::InsertBlockIndex(const BlockHash &hash) { | ||||
mi = mapBlockIndex.insert(std::make_pair(hash, pindexNew)).first; | mi = mapBlockIndex.insert(std::make_pair(hash, pindexNew)).first; | ||||
pindexNew->phashBlock = &((*mi).first); | pindexNew->phashBlock = &((*mi).first); | ||||
return pindexNew; | return pindexNew; | ||||
} | } | ||||
bool CChainState::LoadBlockIndex(const Config &config, | bool CChainState::LoadBlockIndex(const Config &config, | ||||
CBlockTreeDB &blocktree) { | CBlockTreeDB &blocktree) { | ||||
AssertLockHeld(cs_main); | |||||
if (!blocktree.LoadBlockIndexGuts( | if (!blocktree.LoadBlockIndexGuts( | ||||
config.GetChainParams().GetConsensus(), | config.GetChainParams().GetConsensus(), | ||||
[this](const BlockHash &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | [this](const BlockHash &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | ||||
return this->InsertBlockIndex(hash); | return this->InsertBlockIndex(hash); | ||||
})) { | })) { | ||||
return false; | return false; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 63 Lines • ▼ Show 20 Lines | for (const std::pair<int, CBlockIndex *> &item : vSortedByHeight) { | ||||
CBlockIndexWorkComparator()(pindexBestHeader, pindex))) { | CBlockIndexWorkComparator()(pindexBestHeader, pindex))) { | ||||
pindexBestHeader = pindex; | pindexBestHeader = pindex; | ||||
} | } | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
bool static LoadBlockIndexDB(const Config &config) | static bool LoadBlockIndexDB(const Config &config) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | ||||
if (!g_chainstate.LoadBlockIndex(config, *pblocktree)) { | if (!g_chainstate.LoadBlockIndex(config, *pblocktree)) { | ||||
return false; | return false; | ||||
} | } | ||||
// Load block file info | // Load block file info | ||||
pblocktree->ReadLastBlockFile(nLastBlockFile); | pblocktree->ReadLastBlockFile(nLastBlockFile); | ||||
vinfoBlockFile.resize(nLastBlockFile + 1); | vinfoBlockFile.resize(nLastBlockFile + 1); | ||||
▲ Show 20 Lines • Show All 1,238 Lines • Show Last 20 Lines |