diff options
-rw-r--r-- | src/init.cpp | 6 | ||||
-rw-r--r-- | src/net_processing.cpp | 4 | ||||
-rw-r--r-- | src/rpc/blockchain.cpp | 16 | ||||
-rw-r--r-- | src/test/util/setup_common.cpp | 2 | ||||
-rw-r--r-- | src/txmempool.cpp | 11 | ||||
-rw-r--r-- | src/txmempool.h | 2 | ||||
-rw-r--r-- | src/validation.cpp | 145 | ||||
-rw-r--r-- | src/validation.h | 37 | ||||
-rw-r--r-- | src/versionbits.h | 3 |
9 files changed, 101 insertions, 125 deletions
diff --git a/src/init.cpp b/src/init.cpp index f760c069ac..8aa80eacca 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -720,7 +720,7 @@ static void ThreadImport(ChainstateManager& chainman, std::vector<fs::path> vImp fReindex = false; LogPrintf("Reindexing finished\n"); // To avoid ending up in a situation without genesis block, re-try initializing (no-op if reindexing worked): - LoadGenesisBlock(chainparams); + ::ChainstateActive().LoadGenesisBlock(chainparams); } // -loadblock= @@ -1636,7 +1636,7 @@ bool AppInitMain(const util::Ref& context, NodeContext& node, interfaces::BlockA // If we're not mid-reindex (based on disk + args), add a genesis block on disk // (otherwise we use the one already on disk). // This is called again in ThreadImport after the reindex completes. - if (!fReindex && !LoadGenesisBlock(chainparams)) { + if (!fReindex && !::ChainstateActive().LoadGenesisBlock(chainparams)) { strLoadError = _("Error initializing block database"); break; } @@ -1747,7 +1747,7 @@ bool AppInitMain(const util::Ref& context, NodeContext& node, interfaces::BlockA // work when we allow VerifyDB to be parameterized by chainstate. if (&::ChainstateActive() == chainstate && !CVerifyDB().VerifyDB( - chainparams, &chainstate->CoinsDB(), + chainparams, *chainstate, &chainstate->CoinsDB(), args.GetArg("-checklevel", DEFAULT_CHECKLEVEL), args.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS))) { strLoadError = _("Corrupted block database detected"); diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 2e06f03b86..d19e11f7b1 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -2100,7 +2100,7 @@ void PeerManagerImpl::ProcessOrphanTx(std::set<uint256>& orphan_work_set) break; } } - m_mempool.check(&::ChainstateActive().CoinsTip()); + m_mempool.check(m_chainman.ActiveChainstate()); } /** @@ -3061,7 +3061,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type, const TxValidationState& state = result.m_state; if (result.m_result_type == MempoolAcceptResult::ResultType::VALID) { - m_mempool.check(&::ChainstateActive().CoinsTip()); + m_mempool.check(m_chainman.ActiveChainstate()); // As this version of the transaction was acceptable, we can forget about any // requests for it. m_txrequest.ForgetTxHash(tx.GetHash()); diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index c71d2cbe49..ab0c0b8385 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1015,7 +1015,7 @@ static RPCHelpMan pruneblockchain() height = chainHeight - MIN_BLOCKS_TO_KEEP; } - PruneBlockFilesManual(height); + PruneBlockFilesManual(::ChainstateActive(), height); const CBlockIndex* block = ::ChainActive().Tip(); CHECK_NONFATAL(block); while (block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA)) { @@ -1200,7 +1200,7 @@ static RPCHelpMan verifychain() LOCK(cs_main); - return CVerifyDB().VerifyDB(Params(), &::ChainstateActive().CoinsTip(), check_level, check_depth); + return CVerifyDB().VerifyDB(Params(), ::ChainstateActive(), &::ChainstateActive().CoinsTip(), check_level, check_depth); }, }; } @@ -1232,7 +1232,7 @@ static void BIP9SoftForkDescPushBack(UniValue& softforks, const std::string &nam if (consensusParams.vDeployments[id].nTimeout <= 1230768000) return; UniValue bip9(UniValue::VOBJ); - const ThresholdState thresholdState = VersionBitsTipState(consensusParams, id); + const ThresholdState thresholdState = VersionBitsState(::ChainActive().Tip(), consensusParams, id, versionbitscache); switch (thresholdState) { case ThresholdState::DEFINED: bip9.pushKV("status", "defined"); break; case ThresholdState::STARTED: bip9.pushKV("status", "started"); break; @@ -1246,12 +1246,12 @@ static void BIP9SoftForkDescPushBack(UniValue& softforks, const std::string &nam } bip9.pushKV("start_time", consensusParams.vDeployments[id].nStartTime); bip9.pushKV("timeout", consensusParams.vDeployments[id].nTimeout); - int64_t since_height = VersionBitsTipStateSinceHeight(consensusParams, id); + int64_t since_height = VersionBitsStateSinceHeight(::ChainActive().Tip(), consensusParams, id, versionbitscache); bip9.pushKV("since", since_height); if (ThresholdState::STARTED == thresholdState) { UniValue statsUV(UniValue::VOBJ); - BIP9Stats statsStruct = VersionBitsTipStatistics(consensusParams, id); + BIP9Stats statsStruct = VersionBitsStatistics(::ChainActive().Tip(), consensusParams, id); statsUV.pushKV("period", statsStruct.period); statsUV.pushKV("threshold", statsStruct.threshold); statsUV.pushKV("elapsed", statsStruct.elapsed); @@ -1562,7 +1562,7 @@ static RPCHelpMan preciousblock() } BlockValidationState state; - PreciousBlock(state, Params(), pblockindex); + ::ChainstateActive().PreciousBlock(state, Params(), pblockindex); if (!state.IsValid()) { throw JSONRPCError(RPC_DATABASE_ERROR, state.ToString()); @@ -1598,7 +1598,7 @@ static RPCHelpMan invalidateblock() throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); } } - InvalidateBlock(state, Params(), pblockindex); + ::ChainstateActive().InvalidateBlock(state, Params(), pblockindex); if (state.IsValid()) { ::ChainstateActive().ActivateBestChain(state, Params()); @@ -1637,7 +1637,7 @@ static RPCHelpMan reconsiderblock() throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); } - ResetBlockFailureFlags(pblockindex); + ::ChainstateActive().ResetBlockFailureFlags(pblockindex); } BlockValidationState state; diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index 1ffe435531..46b28190d3 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -179,7 +179,7 @@ TestingSetup::TestingSetup(const std::string& chainName, const std::vector<const assert(!::ChainstateActive().CanFlushToDisk()); ::ChainstateActive().InitCoinsCache(1 << 23); assert(::ChainstateActive().CanFlushToDisk()); - if (!LoadGenesisBlock(chainparams)) { + if (!::ChainstateActive().LoadGenesisBlock(chainparams)) { throw std::runtime_error("LoadGenesisBlock failed."); } diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 48424a75d0..f10b4ad740 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -619,7 +619,7 @@ static void CheckInputsAndUpdateCoins(const CTransaction& tx, CCoinsViewCache& m UpdateCoins(tx, mempoolDuplicate, std::numeric_limits<int>::max()); } -void CTxMemPool::check(const CCoinsViewCache *pcoins) const +void CTxMemPool::check(CChainState& active_chainstate) const { if (m_check_ratio == 0) return; @@ -633,8 +633,11 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const CAmount check_total_fee{0}; uint64_t innerUsage = 0; - CCoinsViewCache mempoolDuplicate(const_cast<CCoinsViewCache*>(pcoins)); - const int64_t spendheight = g_chainman.m_blockman.GetSpendHeight(mempoolDuplicate); + CCoinsViewCache& active_coins_tip = active_chainstate.CoinsTip(); + assert(std::addressof(::ChainstateActive().CoinsTip()) == std::addressof(active_coins_tip)); // TODO: REVIEW-ONLY, REMOVE IN FUTURE COMMIT + CCoinsViewCache mempoolDuplicate(const_cast<CCoinsViewCache*>(&active_coins_tip)); + const int64_t spendheight = active_chainstate.m_chain.Height() + 1; + assert(g_chainman.m_blockman.GetSpendHeight(mempoolDuplicate) == spendheight); // TODO: REVIEW-ONLY, REMOVE IN FUTURE COMMIT std::list<const CTxMemPoolEntry*> waitingOnDependants; for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) { @@ -655,7 +658,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const fDependsWait = true; setParentCheck.insert(*it2); } else { - assert(pcoins->HaveCoin(txin.prevout)); + assert(active_coins_tip.HaveCoin(txin.prevout)); } // Check whether its inputs are marked in mapNextTx. auto it3 = mapNextTx.find(txin.prevout); diff --git a/src/txmempool.h b/src/txmempool.h index 143048b205..8a96294192 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -605,7 +605,7 @@ public: * all inputs are in the mapNextTx array). If sanity-checking is turned off, * check does nothing. */ - void check(const CCoinsViewCache *pcoins) const EXCLUSIVE_LOCKS_REQUIRED(::cs_main); + void check(CChainState& active_chainstate) const EXCLUSIVE_LOCKS_REQUIRED(::cs_main); // addUnchecked must updated state for all ancestors of a given transaction, // to track size/count of descendant transactions. First version of diff --git a/src/validation.cpp b/src/validation.cpp index 0b2ca4b422..e7439a2a1a 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -211,6 +211,7 @@ static FlatFileSeq UndoFileSeq(); bool CheckFinalTx(const CBlockIndex* active_chain_tip, const CTransaction &tx, int flags) { AssertLockHeld(cs_main); + assert(active_chain_tip); // TODO: Make active_chain_tip a reference assert(std::addressof(*::ChainActive().Tip()) == std::addressof(*active_chain_tip)); // By convention a negative value for flags indicates that the @@ -221,12 +222,12 @@ bool CheckFinalTx(const CBlockIndex* active_chain_tip, const CTransaction &tx, i // scheduled, so no flags are set. flags = std::max(flags, 0); - // CheckFinalTx() uses ::ChainActive().Height()+1 to evaluate + // CheckFinalTx() uses active_chain_tip.Height()+1 to evaluate // nLockTime because when IsFinalTx() is called within // CBlock::AcceptBlock(), the height of the block *being* // evaluated is what is used. Thus if we want to know if a // transaction can be part of the *next* block, we need to call - // IsFinalTx() with one more than ::ChainActive().Height(). + // IsFinalTx() with one more than active_chain_tip.Height(). const int nBlockHeight = active_chain_tip->nHeight + 1; // BIP113 requires that time-locked transactions have nLockTime set to @@ -1362,16 +1363,18 @@ static void AlertNotify(const std::string& strMessage) #endif } -static void CheckForkWarningConditions() EXCLUSIVE_LOCKS_REQUIRED(cs_main) +void CChainState::CheckForkWarningConditions() { AssertLockHeld(cs_main); + assert(std::addressof(::ChainstateActive()) == std::addressof(*this)); + // Before we get past initial download, we cannot reliably alert about forks // (we assume we don't get stuck on a fork before finishing our initial sync) - if (::ChainstateActive().IsInitialBlockDownload()) { + if (IsInitialBlockDownload()) { return; } - if (pindexBestInvalid && pindexBestInvalid->nChainWork > ::ChainActive().Tip()->nChainWork + (GetBlockProof(*::ChainActive().Tip()) * 6)) { + if (pindexBestInvalid && pindexBestInvalid->nChainWork > m_chain.Tip()->nChainWork + (GetBlockProof(*m_chain.Tip()) * 6)) { LogPrintf("%s: Warning: Found invalid chain at least ~6 blocks longer than our best chain.\nChain state database corruption likely.\n", __func__); SetfLargeWorkInvalidChainFound(true); } else { @@ -1380,21 +1383,22 @@ static void CheckForkWarningConditions() EXCLUSIVE_LOCKS_REQUIRED(cs_main) } // Called both upon regular invalid block discovery *and* InvalidateBlock -void static InvalidChainFound(CBlockIndex* pindexNew) EXCLUSIVE_LOCKS_REQUIRED(cs_main) +void CChainState::InvalidChainFound(CBlockIndex* pindexNew) { + assert(std::addressof(::ChainstateActive()) == std::addressof(*this)); if (!pindexBestInvalid || pindexNew->nChainWork > pindexBestInvalid->nChainWork) pindexBestInvalid = pindexNew; if (pindexBestHeader != nullptr && pindexBestHeader->GetAncestor(pindexNew->nHeight) == pindexNew) { - pindexBestHeader = ::ChainActive().Tip(); + pindexBestHeader = m_chain.Tip(); } LogPrintf("%s: invalid block=%s height=%d log2_work=%f date=%s\n", __func__, pindexNew->GetBlockHash().ToString(), pindexNew->nHeight, log(pindexNew->nChainWork.getdouble())/log(2.0), FormatISO8601DateTime(pindexNew->GetBlockTime())); - CBlockIndex *tip = ::ChainActive().Tip(); + CBlockIndex *tip = m_chain.Tip(); assert (tip); LogPrintf("%s: current best=%s height=%d log2_work=%f date=%s\n", __func__, - tip->GetBlockHash().ToString(), ::ChainActive().Height(), log(tip->nChainWork.getdouble())/log(2.0), + tip->GetBlockHash().ToString(), m_chain.Height(), log(tip->nChainWork.getdouble())/log(2.0), FormatISO8601DateTime(tip->GetBlockTime())); CheckForkWarningConditions(); } @@ -2432,7 +2436,7 @@ static void AppendWarning(bilingual_str& res, const bilingual_str& warn) } /** Check warning conditions and do some notifications on new chain tip set. */ -static void UpdateTip(CTxMemPool& mempool, const CBlockIndex* pindexNew, const CChainParams& chainParams) +static void UpdateTip(CTxMemPool& mempool, const CBlockIndex* pindexNew, const CChainParams& chainParams, CChainState& active_chainstate) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { // New best block @@ -2445,7 +2449,8 @@ static void UpdateTip(CTxMemPool& mempool, const CBlockIndex* pindexNew, const C } bilingual_str warning_messages; - if (!::ChainstateActive().IsInitialBlockDownload()) { + assert(std::addressof(::ChainstateActive()) == std::addressof(active_chainstate)); + if (!active_chainstate.IsInitialBlockDownload()) { const CBlockIndex* pindex = pindexNew; for (int bit = 0; bit < VERSIONBITS_NUM_BITS; bit++) { WarningBitsConditionChecker checker(bit); @@ -2460,11 +2465,12 @@ static void UpdateTip(CTxMemPool& mempool, const CBlockIndex* pindexNew, const C } } } + assert(std::addressof(::ChainstateActive()) == std::addressof(active_chainstate)); LogPrintf("%s: new best=%s height=%d version=0x%08x log2_work=%f tx=%lu date='%s' progress=%f cache=%.1fMiB(%utxo)%s\n", __func__, pindexNew->GetBlockHash().ToString(), pindexNew->nHeight, pindexNew->nVersion, log(pindexNew->nChainWork.getdouble())/log(2.0), (unsigned long)pindexNew->nChainTx, FormatISO8601DateTime(pindexNew->GetBlockTime()), - GuessVerificationProgress(chainParams.TxData(), pindexNew), ::ChainstateActive().CoinsTip().DynamicMemoryUsage() * (1.0 / (1<<20)), ::ChainstateActive().CoinsTip().GetCacheSize(), + GuessVerificationProgress(chainParams.TxData(), pindexNew), active_chainstate.CoinsTip().DynamicMemoryUsage() * (1.0 / (1<<20)), active_chainstate.CoinsTip().GetCacheSize(), !warning_messages.empty() ? strprintf(" warning='%s'", warning_messages.original) : ""); } @@ -2520,7 +2526,7 @@ bool CChainState::DisconnectTip(BlockValidationState& state, const CChainParams& m_chain.SetTip(pindexDelete->pprev); - UpdateTip(m_mempool, pindexDelete->pprev, chainparams); + UpdateTip(m_mempool, pindexDelete->pprev, chainparams, *this); // Let wallets know transactions went from 1-confirmed to // 0-confirmed or conflicted: GetMainSignals().BlockDisconnected(pblock, pindexDelete); @@ -2628,7 +2634,7 @@ bool CChainState::ConnectTip(BlockValidationState& state, const CChainParams& ch disconnectpool.removeForBlock(blockConnecting.vtx); // Update m_chain & related variables. m_chain.SetTip(pindexNew); - UpdateTip(m_mempool, pindexNew, chainparams); + UpdateTip(m_mempool, pindexNew, chainparams, *this); int64_t nTime6 = GetTimeMicros(); nTimePostConnect += nTime6 - nTime5; nTimeTotal += nTime6 - nTime1; LogPrint(BCLog::BENCH, " - Connect postprocess: %.2fms [%.2fs (%.2fms/blk)]\n", (nTime6 - nTime5) * MILLI, nTimePostConnect * MICRO, nTimePostConnect * MILLI / nBlocksTotal); @@ -2719,6 +2725,7 @@ bool CChainState::ActivateBestChainStep(BlockValidationState& state, const CChai { AssertLockHeld(cs_main); AssertLockHeld(m_mempool.cs); + assert(std::addressof(::ChainstateActive()) == std::addressof(*this)); const CBlockIndex* pindexOldTip = m_chain.Tip(); const CBlockIndex* pindexFork = m_chain.FindFork(pindexMostWork); @@ -2730,7 +2737,7 @@ bool CChainState::ActivateBestChainStep(BlockValidationState& state, const CChai if (!DisconnectTip(state, chainparams, &disconnectpool)) { // This is likely a fatal error, but keep the mempool consistent, // just in case. Only remove from the mempool in this case. - UpdateMempoolForReorg(::ChainstateActive(), m_mempool, disconnectpool, false); + UpdateMempoolForReorg(*this, m_mempool, disconnectpool, false); // If we're unable to disconnect a block during normal operation, // then that is a failure of our local system -- we should abort @@ -2774,7 +2781,7 @@ bool CChainState::ActivateBestChainStep(BlockValidationState& state, const CChai // A system error occurred (disk space, database error, ...). // Make the mempool consistent with the current tip, just in case // any observers try to use it before shutdown. - UpdateMempoolForReorg(::ChainstateActive(), m_mempool, disconnectpool, false); + UpdateMempoolForReorg(*this, m_mempool, disconnectpool, false); return false; } } else { @@ -2791,9 +2798,9 @@ bool CChainState::ActivateBestChainStep(BlockValidationState& state, const CChai if (fBlocksDisconnected) { // If any blocks were disconnected, disconnectpool may be non empty. Add // any disconnected transactions back to the mempool. - UpdateMempoolForReorg(::ChainstateActive(), m_mempool, disconnectpool, true); + UpdateMempoolForReorg(*this, m_mempool, disconnectpool, true); } - m_mempool.check(&CoinsTip()); + m_mempool.check(*this); CheckForkWarningConditions(); @@ -2964,9 +2971,6 @@ bool CChainState::PreciousBlock(BlockValidationState& state, const CChainParams& return ActivateBestChain(state, params, std::shared_ptr<const CBlock>()); } -bool PreciousBlock(BlockValidationState& state, const CChainParams& params, CBlockIndex *pindex) { - return ::ChainstateActive().PreciousBlock(state, params, pindex); -} bool CChainState::InvalidateBlock(BlockValidationState& state, const CChainParams& chainparams, CBlockIndex *pindex) { @@ -3028,7 +3032,8 @@ bool CChainState::InvalidateBlock(BlockValidationState& state, const CChainParam // transactions back to the mempool if disconnecting was successful, // and we're not doing a very deep invalidation (in which case // keeping the mempool up to date is probably futile anyway). - UpdateMempoolForReorg(::ChainstateActive(), m_mempool, disconnectpool, /* fAddToMempool = */ (++disconnected <= 10) && ret); + assert(std::addressof(::ChainstateActive()) == std::addressof(*this)); + UpdateMempoolForReorg(*this, m_mempool, disconnectpool, /* fAddToMempool = */ (++disconnected <= 10) && ret); if (!ret) return false; assert(invalid_walk_tip->pprev == m_chain.Tip()); @@ -3104,10 +3109,6 @@ bool CChainState::InvalidateBlock(BlockValidationState& state, const CChainParam return true; } -bool InvalidateBlock(BlockValidationState& state, const CChainParams& chainparams, CBlockIndex *pindex) { - return ::ChainstateActive().InvalidateBlock(state, chainparams, pindex); -} - void CChainState::ResetBlockFailureFlags(CBlockIndex *pindex) { AssertLockHeld(cs_main); @@ -3142,10 +3143,6 @@ void CChainState::ResetBlockFailureFlags(CBlockIndex *pindex) { } } -void ResetBlockFailureFlags(CBlockIndex *pindex) { - return ::ChainstateActive().ResetBlockFailureFlags(pindex); -} - CBlockIndex* BlockManager::AddToBlockIndex(const CBlockHeader& block) { AssertLockHeld(cs_main); @@ -3229,7 +3226,7 @@ void CChainState::ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pi } } -static bool FindBlockPos(FlatFilePos &pos, unsigned int nAddSize, unsigned int nHeight, uint64_t nTime, bool fKnown = false) +static bool FindBlockPos(FlatFilePos &pos, unsigned int nAddSize, unsigned int nHeight, CChain& active_chain, uint64_t nTime, bool fKnown = false) { LOCK(cs_LastBlockFile); @@ -3244,7 +3241,8 @@ static bool FindBlockPos(FlatFilePos &pos, unsigned int nAddSize, unsigned int n // when the undo file is keeping up with the block file, we want to flush it explicitly // when it is lagging behind (more blocks arrive than are being connected), we let the // undo block write case handle it - finalize_undo = (vinfoBlockFile[nFile].nHeightLast == (unsigned int)ChainActive().Tip()->nHeight); + assert(std::addressof(::ChainActive()) == std::addressof(active_chain)); + finalize_undo = (vinfoBlockFile[nFile].nHeightLast == (unsigned int)active_chain.Tip()->nHeight); nFile++; if (vinfoBlockFile.size() <= nFile) { vinfoBlockFile.resize(nFile + 1); @@ -3706,12 +3704,12 @@ bool ChainstateManager::ProcessNewBlockHeaders(const std::vector<CBlockHeader>& } /** Store block on disk. If dbp is non-nullptr, the file is known to already reside on disk */ -static FlatFilePos SaveBlockToDisk(const CBlock& block, int nHeight, const CChainParams& chainparams, const FlatFilePos* dbp) { +static FlatFilePos SaveBlockToDisk(const CBlock& block, int nHeight, CChain& active_chain, const CChainParams& chainparams, const FlatFilePos* dbp) { unsigned int nBlockSize = ::GetSerializeSize(block, CLIENT_VERSION); FlatFilePos blockPos; if (dbp != nullptr) blockPos = *dbp; - if (!FindBlockPos(blockPos, nBlockSize+8, nHeight, block.GetBlockTime(), dbp != nullptr)) { + if (!FindBlockPos(blockPos, nBlockSize+8, nHeight, active_chain, block.GetBlockTime(), dbp != nullptr)) { error("%s: FindBlockPos failed", __func__); return FlatFilePos(); } @@ -3789,8 +3787,9 @@ bool CChainState::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, Block // Write block to history file if (fNewBlock) *fNewBlock = true; + assert(std::addressof(::ChainActive()) == std::addressof(m_chain)); try { - FlatFilePos blockPos = SaveBlockToDisk(block, pindex->nHeight, chainparams, dbp); + FlatFilePos blockPos = SaveBlockToDisk(block, pindex->nHeight, m_chain, chainparams, dbp); if (blockPos.IsNull()) { state.Error(strprintf("%s: Failed to find position to write new block to disk", __func__)); return false; @@ -3961,11 +3960,12 @@ void BlockManager::FindFilesToPruneManual(std::set<int>& setFilesToPrune, int nM } /* This function is called from the RPC code for pruneblockchain */ -void PruneBlockFilesManual(int nManualPruneHeight) +void PruneBlockFilesManual(CChainState& active_chainstate, int nManualPruneHeight) { BlockValidationState state; const CChainParams& chainparams = Params(); - if (!::ChainstateActive().FlushStateToDisk( + assert(std::addressof(::ChainstateActive()) == std::addressof(active_chainstate)); + if (!active_chainstate.FlushStateToDisk( chainparams, state, FlushStateMode::NONE, nManualPruneHeight)) { LogPrintf("%s: failed to flush state (%s)\n", __func__, state.ToString()); } @@ -4140,11 +4140,12 @@ void BlockManager::Unload() { m_block_index.clear(); } -bool static LoadBlockIndexDB(ChainstateManager& chainman, const CChainParams& chainparams) EXCLUSIVE_LOCKS_REQUIRED(cs_main) +bool CChainState::LoadBlockIndexDB(const CChainParams& chainparams) { - if (!chainman.m_blockman.LoadBlockIndex( + assert(std::addressof(::ChainstateActive()) == std::addressof(*this)); + if (!m_blockman.LoadBlockIndex( chainparams.GetConsensus(), *pblocktree, - ::ChainstateActive().setBlockIndexCandidates)) { + setBlockIndexCandidates)) { return false; } @@ -4168,7 +4169,7 @@ bool static LoadBlockIndexDB(ChainstateManager& chainman, const CChainParams& ch // Check presence of blk files LogPrintf("Checking all blk files are present...\n"); std::set<int> setBlkDataFiles; - for (const std::pair<const uint256, CBlockIndex*>& item : chainman.BlockIndex()) { + for (const std::pair<const uint256, CBlockIndex*>& item : m_blockman.m_block_index) { CBlockIndex* pindex = item.second; if (pindex->nStatus & BLOCK_HAVE_DATA) { setBlkDataFiles.insert(pindex->nFile); @@ -4242,15 +4243,17 @@ CVerifyDB::~CVerifyDB() uiInterface.ShowProgress("", 100, false); } -bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, int nCheckLevel, int nCheckDepth) +bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CChainState& active_chainstate, CCoinsView *coinsview, int nCheckLevel, int nCheckDepth) { - LOCK(cs_main); - if (::ChainActive().Tip() == nullptr || ::ChainActive().Tip()->pprev == nullptr) + AssertLockHeld(cs_main); + + assert(std::addressof(::ChainstateActive()) == std::addressof(active_chainstate)); + if (active_chainstate.m_chain.Tip() == nullptr || active_chainstate.m_chain.Tip()->pprev == nullptr) return true; // Verify blocks in the best chain - if (nCheckDepth <= 0 || nCheckDepth > ::ChainActive().Height()) - nCheckDepth = ::ChainActive().Height(); + if (nCheckDepth <= 0 || nCheckDepth > active_chainstate.m_chain.Height()) + nCheckDepth = active_chainstate.m_chain.Height(); nCheckLevel = std::max(0, std::min(4, nCheckLevel)); LogPrintf("Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel); CCoinsViewCache coins(coinsview); @@ -4260,15 +4263,15 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, BlockValidationState state; int reportDone = 0; LogPrintf("[0%%]..."); /* Continued */ - for (pindex = ::ChainActive().Tip(); pindex && pindex->pprev; pindex = pindex->pprev) { - const int percentageDone = std::max(1, std::min(99, (int)(((double)(::ChainActive().Height() - pindex->nHeight)) / (double)nCheckDepth * (nCheckLevel >= 4 ? 50 : 100)))); + for (pindex = active_chainstate.m_chain.Tip(); pindex && pindex->pprev; pindex = pindex->pprev) { + const int percentageDone = std::max(1, std::min(99, (int)(((double)(active_chainstate.m_chain.Height() - pindex->nHeight)) / (double)nCheckDepth * (nCheckLevel >= 4 ? 50 : 100)))); if (reportDone < percentageDone/10) { // report every 10% step LogPrintf("[%d%%]...", percentageDone); /* Continued */ reportDone = percentageDone/10; } uiInterface.ShowProgress(_("Verifying blocks...").translated, percentageDone, false); - if (pindex->nHeight <= ::ChainActive().Height()-nCheckDepth) + if (pindex->nHeight <= active_chainstate.m_chain.Height()-nCheckDepth) break; if (fPruneMode && !(pindex->nStatus & BLOCK_HAVE_DATA)) { // If pruning, only go back as far as we have data. @@ -4293,9 +4296,9 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, } } // check level 3: check for inconsistencies during memory-only disconnect of tip blocks - if (nCheckLevel >= 3 && (coins.DynamicMemoryUsage() + ::ChainstateActive().CoinsTip().DynamicMemoryUsage()) <= ::ChainstateActive().m_coinstip_cache_size_bytes) { + if (nCheckLevel >= 3 && (coins.DynamicMemoryUsage() + active_chainstate.CoinsTip().DynamicMemoryUsage()) <= active_chainstate.m_coinstip_cache_size_bytes) { assert(coins.GetBestBlock() == pindex->GetBlockHash()); - DisconnectResult res = ::ChainstateActive().DisconnectBlock(block, pindex, coins); + DisconnectResult res = active_chainstate.DisconnectBlock(block, pindex, coins); if (res == DISCONNECT_FAILED) { return error("VerifyDB(): *** irrecoverable inconsistency in block data at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); } @@ -4309,26 +4312,26 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, if (ShutdownRequested()) return true; } if (pindexFailure) - return error("VerifyDB(): *** coin database inconsistencies found (last %i blocks, %i good transactions before that)\n", ::ChainActive().Height() - pindexFailure->nHeight + 1, nGoodTransactions); + return error("VerifyDB(): *** coin database inconsistencies found (last %i blocks, %i good transactions before that)\n", active_chainstate.m_chain.Height() - pindexFailure->nHeight + 1, nGoodTransactions); // store block count as we move pindex at check level >= 4 - int block_count = ::ChainActive().Height() - pindex->nHeight; + int block_count = active_chainstate.m_chain.Height() - pindex->nHeight; // check level 4: try reconnecting blocks if (nCheckLevel >= 4) { - while (pindex != ::ChainActive().Tip()) { - const int percentageDone = std::max(1, std::min(99, 100 - (int)(((double)(::ChainActive().Height() - pindex->nHeight)) / (double)nCheckDepth * 50))); + while (pindex != active_chainstate.m_chain.Tip()) { + const int percentageDone = std::max(1, std::min(99, 100 - (int)(((double)(active_chainstate.m_chain.Height() - pindex->nHeight)) / (double)nCheckDepth * 50))); if (reportDone < percentageDone/10) { // report every 10% step LogPrintf("[%d%%]...", percentageDone); /* Continued */ reportDone = percentageDone/10; } uiInterface.ShowProgress(_("Verifying blocks...").translated, percentageDone, false); - pindex = ::ChainActive().Next(pindex); + pindex = active_chainstate.m_chain.Next(pindex); CBlock block; if (!ReadBlockFromDisk(block, pindex, chainparams.GetConsensus())) return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); - if (!::ChainstateActive().ConnectBlock(block, state, pindex, coins, chainparams)) + if (!active_chainstate.ConnectBlock(block, state, pindex, coins, chainparams)) return error("VerifyDB(): *** found unconnectable block at %d, hash=%s (%s)", pindex->nHeight, pindex->GetBlockHash().ToString(), state.ToString()); if (ShutdownRequested()) return true; } @@ -4599,7 +4602,7 @@ bool ChainstateManager::LoadBlockIndex(const CChainParams& chainparams) // Load block index from databases bool needs_init = fReindex; if (!fReindex) { - bool ret = LoadBlockIndexDB(*this, chainparams); + bool ret = ActiveChainstate().LoadBlockIndexDB(chainparams); if (!ret) return false; needs_init = m_blockman.m_block_index.empty(); } @@ -4627,9 +4630,10 @@ bool CChainState::LoadGenesisBlock(const CChainParams& chainparams) if (m_blockman.m_block_index.count(chainparams.GenesisBlock().GetHash())) return true; + assert(std::addressof(::ChainActive()) == std::addressof(m_chain)); try { const CBlock& block = chainparams.GenesisBlock(); - FlatFilePos blockPos = SaveBlockToDisk(block, 0, chainparams, nullptr); + FlatFilePos blockPos = SaveBlockToDisk(block, 0, m_chain, chainparams, nullptr); if (blockPos.IsNull()) return error("%s: writing genesis block to disk failed", __func__); CBlockIndex *pindex = m_blockman.AddToBlockIndex(block); @@ -4641,11 +4645,6 @@ bool CChainState::LoadGenesisBlock(const CChainParams& chainparams) return true; } -bool LoadGenesisBlock(const CChainParams& chainparams) -{ - return ::ChainstateActive().LoadGenesisBlock(chainparams); -} - void CChainState::LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, FlatFilePos* dbp) { // Map of disk positions for blocks with unknown parent (only used for reindex) @@ -5009,24 +5008,6 @@ CBlockFileInfo* GetBlockFileInfo(size_t n) return &vinfoBlockFile.at(n); } -ThresholdState VersionBitsTipState(const Consensus::Params& params, Consensus::DeploymentPos pos) -{ - LOCK(cs_main); - return VersionBitsState(::ChainActive().Tip(), params, pos, versionbitscache); -} - -BIP9Stats VersionBitsTipStatistics(const Consensus::Params& params, Consensus::DeploymentPos pos) -{ - LOCK(cs_main); - return VersionBitsStatistics(::ChainActive().Tip(), params, pos); -} - -int VersionBitsTipStateSinceHeight(const Consensus::Params& params, Consensus::DeploymentPos pos) -{ - LOCK(cs_main); - return VersionBitsStateSinceHeight(::ChainActive().Tip(), params, pos, versionbitscache); -} - static const uint64_t MEMPOOL_DUMP_VERSION = 1; bool LoadMempool(CTxMemPool& pool, CChainState& active_chainstate) diff --git a/src/validation.h b/src/validation.h index 4e4bdbea54..74f8541934 100644 --- a/src/validation.h +++ b/src/validation.h @@ -183,7 +183,7 @@ uint64_t CalculateCurrentUsage(); void UnlinkPrunedFiles(const std::set<int>& setFilesToPrune); /** Prune block files up to a given height */ -void PruneBlockFilesManual(int nManualPruneHeight); +void PruneBlockFilesManual(CChainState& active_chainstate, int nManualPruneHeight); /** * Validation result for a single transaction mempool acceptance. @@ -226,15 +226,6 @@ struct MempoolAcceptResult { MempoolAcceptResult AcceptToMemoryPool(CChainState& active_chainstate, CTxMemPool& pool, const CTransactionRef& tx, bool bypass_limits, bool test_accept=false) EXCLUSIVE_LOCKS_REQUIRED(cs_main); -/** Get the BIP9 state for a given deployment at the current tip. */ -ThresholdState VersionBitsTipState(const Consensus::Params& params, Consensus::DeploymentPos pos); - -/** Get the numerical statistics for the BIP9 state for a given deployment at the current tip. */ -BIP9Stats VersionBitsTipStatistics(const Consensus::Params& params, Consensus::DeploymentPos pos); - -/** Get the block height at which the BIP9 deployment switched into the state for the block building on the current tip. */ -int VersionBitsTipStateSinceHeight(const Consensus::Params& params, Consensus::DeploymentPos pos); - /** Apply the effects of this transaction on the UTXO set represented by view */ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight); @@ -349,7 +340,7 @@ class CVerifyDB { public: CVerifyDB(); ~CVerifyDB(); - bool VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, int nCheckLevel, int nCheckDepth); + bool VerifyDB(const CChainParams& chainparams, CChainState& active_chainstate, CCoinsView *coinsview, int nCheckLevel, int nCheckDepth) EXCLUSIVE_LOCKS_REQUIRED(cs_main); }; enum DisconnectResult @@ -721,8 +712,14 @@ public: bool DisconnectTip(BlockValidationState& state, const CChainParams& chainparams, DisconnectedBlockTransactions* disconnectpool) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_mempool.cs); // Manual block validity manipulation: + /** Mark a block as precious and reorganize. + * + * May not be called in a validationinterface callback. + */ bool PreciousBlock(BlockValidationState& state, const CChainParams& params, CBlockIndex* pindex) LOCKS_EXCLUDED(cs_main); + /** Mark a block as invalid. */ bool InvalidateBlock(BlockValidationState& state, const CChainParams& chainparams, CBlockIndex* pindex) LOCKS_EXCLUDED(cs_main); + /** Remove invalidity status from a block and its descendants. */ void ResetBlockFailureFlags(CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main); /** Replay blocks that aren't fully applied to the database. */ @@ -776,21 +773,13 @@ private: //! Mark a block as not having block data void EraseBlockData(CBlockIndex* index) EXCLUSIVE_LOCKS_REQUIRED(cs_main); - friend ChainstateManager; -}; - -/** Mark a block as precious and reorganize. - * - * May not be called in a - * validationinterface callback. - */ -bool PreciousBlock(BlockValidationState& state, const CChainParams& params, CBlockIndex *pindex) LOCKS_EXCLUDED(cs_main); + void CheckForkWarningConditions() EXCLUSIVE_LOCKS_REQUIRED(cs_main); + void InvalidChainFound(CBlockIndex* pindexNew) EXCLUSIVE_LOCKS_REQUIRED(cs_main); -/** Mark a block as invalid. */ -bool InvalidateBlock(BlockValidationState& state, const CChainParams& chainparams, CBlockIndex* pindex) LOCKS_EXCLUDED(cs_main); + bool LoadBlockIndexDB(const CChainParams& chainparams) EXCLUSIVE_LOCKS_REQUIRED(cs_main); -/** Remove invalidity status from a block and its descendants. */ -void ResetBlockFailureFlags(CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main); + friend ChainstateManager; +}; /** * Provides an interface for creating and interacting with one or two diff --git a/src/versionbits.h b/src/versionbits.h index b02f848b67..6df1db8814 100644 --- a/src/versionbits.h +++ b/src/versionbits.h @@ -79,8 +79,11 @@ struct VersionBitsCache void Clear(); }; +/** Get the BIP9 state for a given deployment at the current tip. */ ThresholdState VersionBitsState(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache); +/** Get the numerical statistics for the BIP9 state for a given deployment at the current tip. */ BIP9Stats VersionBitsStatistics(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos); +/** Get the block height at which the BIP9 deployment switched into the state for the block building on the current tip. */ int VersionBitsStateSinceHeight(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache); uint32_t VersionBitsMask(const Consensus::Params& params, Consensus::DeploymentPos pos); |