diff --git a/src/dsnotificationinterface.h b/src/dsnotificationinterface.h index d58d178a1b62..92ee04aac1d3 100644 --- a/src/dsnotificationinterface.h +++ b/src/dsnotificationinterface.h @@ -1,4 +1,4 @@ -// Copyright (c) 2015 The Bitcoin Core developers +// Copyright (c) 2015 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/evo/chainhelper.cpp b/src/evo/chainhelper.cpp index d946785ea1b5..c58c942b535c 100644 --- a/src/evo/chainhelper.cpp +++ b/src/evo/chainhelper.cpp @@ -6,14 +6,9 @@ #include #include -#include #include #include #include -#include -#include - -using node::GetTransaction; CChainstateHelper::CChainstateHelper(CCreditPoolManager& cpoolman, CDeterministicMNManager& dmnman, CMNHFManager& mnhfman, CGovernanceManager& govman, llmq::CInstantSendManager& isman, @@ -64,9 +59,3 @@ bool CChainstateHelper::RemoveConflictingISLockByTx(const CTransaction& tx) bool CChainstateHelper::ShouldInstantSendRejectConflicts() const { return isman.RejectConflictingBlocks(); } -std::pair GetTransactionBlock(const uint256& hash, const CTxMemPool* const mempool) -{ - uint256 hashBlock{}; - if (!g_txindex && !mempool) return {nullptr, hashBlock}; // Fast-fail as we don't have any other way to search - return {GetTransaction(/*block_index=*/nullptr, mempool, hash, Params().GetConsensus(), hashBlock), hashBlock}; -} diff --git a/src/evo/chainhelper.h b/src/evo/chainhelper.h index 374d59b4f128..6dd94bf1941f 100644 --- a/src/evo/chainhelper.h +++ b/src/evo/chainhelper.h @@ -18,7 +18,6 @@ class CGovernanceManager; class CSpecialTxProcessor; class CSporkManager; class CTransaction; -class CTxMemPool; class uint256; namespace Consensus { struct Params; } @@ -30,8 +29,6 @@ class CQuorumManager; class CQuorumSnapshotManager; } -using CTransactionRef = std::shared_ptr; - class CChainstateHelper { private: @@ -66,8 +63,4 @@ class CChainstateHelper const std::unique_ptr special_tx; }; -/* Retrieve transaction and block from txindex (or mempool) */ -std::pair GetTransactionBlock(const uint256& hash, - const CTxMemPool* const mempool = nullptr); - #endif // BITCOIN_EVO_CHAINHELPER_H diff --git a/src/evo/deterministicmns.cpp b/src/evo/deterministicmns.cpp index 38192ca25539..e38e699f5270 100644 --- a/src/evo/deterministicmns.cpp +++ b/src/evo/deterministicmns.cpp @@ -2,13 +2,13 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include #include #include #include #include #include #include +#include #include #include @@ -50,11 +50,15 @@ UniValue CDeterministicMN::ToJson() const obj.pushKV("collateralHash", collateralOutpoint.hash.ToString()); obj.pushKV("collateralIndex", (int)collateralOutpoint.n); - auto [collateralTx, _] = GetTransactionBlock(collateralOutpoint.hash); - if (collateralTx) { - CTxDestination dest; - if (ExtractDestination(collateralTx->vout[collateralOutpoint.n].scriptPubKey, dest)) { - obj.pushKV("collateralAddress", EncodeDestination(dest)); + if (g_txindex) { + CTransactionRef collateralTx; + uint256 nBlockHash; + g_txindex->FindTx(collateralOutpoint.hash, nBlockHash, collateralTx); + if (collateralTx) { + CTxDestination dest; + if (ExtractDestination(collateralTx->vout[collateralOutpoint.n].scriptPubKey, dest)) { + obj.pushKV("collateralAddress", EncodeDestination(dest)); + } } } diff --git a/src/governance/object.cpp b/src/governance/object.cpp index 53c2db8a9761..6c57af78aa86 100644 --- a/src/governance/object.cpp +++ b/src/governance/object.cpp @@ -7,10 +7,10 @@ #include #include #include -#include #include #include #include +#include #include #include #include @@ -453,8 +453,12 @@ bool CGovernanceObject::IsCollateralValid(const ChainstateManager& chainman, std fMissingConfirmations = false; uint256 nExpectedHash = GetHash(); - // RETRIEVE TRANSACTION IN QUESTION - auto [txCollateral, nBlockHash] = GetTransactionBlock(m_obj.collateralHash); + CTransactionRef txCollateral; + uint256 nBlockHash; + if (g_txindex) { + g_txindex->FindTx(m_obj.collateralHash, nBlockHash, txCollateral); + } + if (!txCollateral) { strError = strprintf("Can't find collateral tx %s", m_obj.collateralHash.ToString()); LogPrintf("CGovernanceObject::IsCollateralValid -- %s\n", strError); diff --git a/src/init.cpp b/src/init.cpp index f942e0f93ef4..1b0a8aa8605a 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -2327,7 +2327,31 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) } chainman.m_load_block = std::thread(&util::TraceThread, "loadblk", [=, &args, &chainman, &node] { - ThreadImport(chainman, *node.dmnman, *g_ds_notification_interface, vImportFiles, node.mn_activeman.get(), args); + ThreadImport(chainman, vImportFiles, args); + + // force UpdatedBlockTip to initialize nCachedBlockHeight for DS, MN payments and budgets + // but don't call it directly to prevent triggering of other listeners like zmq etc. + // GetMainSignals().UpdatedBlockTip(::ChainActive().Tip()); + g_ds_notification_interface->InitializeCurrentBlockTip(); + + { + // Get all UTXOs for each MN collateral in one go so that we can fill coin cache early + // and reduce further locking overhead for cs_main in other parts of code including GUI + LogPrintf("Filling coin cache with masternode UTXOs...\n"); + LOCK(cs_main); + const auto start{SteadyClock::now()}; + const auto mnList{node.dmnman->GetListAtChainTip()}; + mnList.ForEachMN(false, [&](auto& dmn) { + Coin coin; + GetUTXOCoin(chainman.ActiveChainstate(), dmn.collateralOutpoint, coin); + }); + LogPrintf("Filling coin cache with masternode UTXOs: done in %dms\n", Ticks(SteadyClock::now() - start)); + } + + if (node.mn_activeman != nullptr) { + node.mn_activeman->Init(chainman.ActiveTip()); + } + }); #ifdef ENABLE_WALLET if (!args.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) { diff --git a/src/llmq/chainlocks.cpp b/src/llmq/chainlocks.cpp index 3364fa3b6637..f25628dfcc15 100644 --- a/src/llmq/chainlocks.cpp +++ b/src/llmq/chainlocks.cpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -26,6 +25,14 @@ using node::ReadBlockFromDisk; +// Forward declaration to break dependency over node/transaction.h +namespace node +{ +CTransactionRef GetTransaction(const CBlockIndex* const block_index, const CTxMemPool* const mempool, + const uint256& hash, const Consensus::Params& consensusParams, uint256& hashBlock); +} // namespace node +using node::GetTransaction; + static bool ChainLocksSigningEnabled(const CSporkManager& sporkman) { return sporkman.GetSporkValue(SPORK_19_CHAINLOCKS_ENABLED) == 0; @@ -638,8 +645,8 @@ void CChainLocksHandler::Cleanup() } } for (auto it = txFirstSeenTime.begin(); it != txFirstSeenTime.end(); ) { - auto [tx, hashBlock] = GetTransactionBlock(it->first, &mempool); - if (!tx) { + uint256 hashBlock; + if (auto tx = GetTransaction(nullptr, &mempool, it->first, Params().GetConsensus(), hashBlock); !tx) { // tx has vanished, probably due to conflicts it = txFirstSeenTime.erase(it); } else if (!hashBlock.IsNull()) { diff --git a/src/llmq/instantsend.cpp b/src/llmq/instantsend.cpp index f80221d51e2f..ff4ed81f2d1f 100644 --- a/src/llmq/instantsend.cpp +++ b/src/llmq/instantsend.cpp @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -31,6 +30,14 @@ using node::fImporting; using node::fReindex; +// Forward declaration to break dependency over node/transaction.h +namespace node +{ +CTransactionRef GetTransaction(const CBlockIndex* const block_index, const CTxMemPool* const mempool, + const uint256& hash, const Consensus::Params& consensusParams, uint256& hashBlock); +} // namespace node +using node::GetTransaction; + namespace llmq { @@ -578,7 +585,8 @@ bool CInstantSendManager::CheckCanLock(const COutPoint& outpoint, bool printDebu return false; } - auto [tx, hashBlock] = GetTransactionBlock(outpoint.hash, &mempool); + uint256 hashBlock{}; + const auto tx = GetTransaction(nullptr, &mempool, outpoint.hash, params, hashBlock); // this relies on enabled txindex and won't work if we ever try to remove the requirement for txindex for masternodes if (!tx) { if (printDebug) { @@ -635,7 +643,9 @@ void CInstantSendManager::HandleNewInputLockRecoveredSig(const CRecoveredSig& re g_txindex->BlockUntilSyncedToCurrentChain(); } - auto [tx, hashBlock] = GetTransactionBlock(txid, &mempool); + + uint256 hashBlock{}; + const auto tx = GetTransaction(nullptr, &mempool, txid, Params().GetConsensus(), hashBlock); if (!tx) { return; } @@ -1017,7 +1027,8 @@ void CInstantSendManager::ProcessInstantSendLock(NodeId from, PeerManager& peerm return; } - auto [tx, hashBlock] = GetTransactionBlock(islock->txid, &mempool); + uint256 hashBlock{}; + const auto tx = GetTransaction(nullptr, &mempool, islock->txid, Params().GetConsensus(), hashBlock); const CBlockIndex* pindexMined{nullptr}; // we ignore failure here as we must be able to propagate the lock even if we don't have the TX locally if (tx && !hashBlock.IsNull()) { diff --git a/src/node/blockstorage.cpp b/src/node/blockstorage.cpp index e97e4ac6f3c9..0a5ca022fa73 100644 --- a/src/node/blockstorage.cpp +++ b/src/node/blockstorage.cpp @@ -8,12 +8,9 @@ #include #include #include -#include -#include #include #include #include -#include #include #include #include @@ -825,8 +822,7 @@ struct CImportingNow { } }; -void ThreadImport(ChainstateManager& chainman, CDeterministicMNManager& dmnman, CDSNotificationInterface& dsnfi, - std::vector vImportFiles, CActiveMasternodeManager* const mn_activeman, const ArgsManager& args) +void ThreadImport(ChainstateManager& chainman, std::vector vImportFiles, const ArgsManager& args) { ScheduleBatchPriority(); @@ -899,29 +895,6 @@ void ThreadImport(ChainstateManager& chainman, CDeterministicMNManager& dmnman, } } // End scope of CImportingNow - // force UpdatedBlockTip to initialize nCachedBlockHeight for DS, MN payments and budgets - // but don't call it directly to prevent triggering of other listeners like zmq etc. - // GetMainSignals().UpdatedBlockTip(::ChainActive().Tip()); - dsnfi.InitializeCurrentBlockTip(); - - { - // Get all UTXOs for each MN collateral in one go so that we can fill coin cache early - // and reduce further locking overhead for cs_main in other parts of code including GUI - LogPrintf("Filling coin cache with masternode UTXOs...\n"); - LOCK(cs_main); - const auto start{SteadyClock::now()}; - auto mnList = dmnman.GetListAtChainTip(); - mnList.ForEachMN(false, [&](auto& dmn) { - Coin coin; - GetUTXOCoin(chainman.ActiveChainstate(), dmn.collateralOutpoint, coin); - }); - LogPrintf("Filling coin cache with masternode UTXOs: done in %dms\n", Ticks(SteadyClock::now() - start)); - } - - if (mn_activeman != nullptr) { - mn_activeman->Init(chainman.ActiveTip()); - } - chainman.ActiveChainstate().LoadMempool(args); } } // namespace node diff --git a/src/node/blockstorage.h b/src/node/blockstorage.h index 128fb884ac4b..b627c26162fd 100644 --- a/src/node/blockstorage.h +++ b/src/node/blockstorage.h @@ -18,7 +18,6 @@ extern RecursiveMutex cs_main; -class CActiveMasternodeManager; class ArgsManager; class BlockValidationState; class CBlock; @@ -26,8 +25,6 @@ class CBlockUndo; class CChain; class CChainParams; class CChainState; -class CDeterministicMNManager; -class CDSNotificationInterface; class ChainstateManager; struct CCheckpointData; struct FlatFilePos; @@ -229,8 +226,7 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus bool UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex* pindex); -void ThreadImport(ChainstateManager& chainman, CDeterministicMNManager& dmnman, CDSNotificationInterface& dsnfi, - std::vector vImportFiles, CActiveMasternodeManager* const mn_activeman, const ArgsManager& args); +void ThreadImport(ChainstateManager& chainman, std::vector vImportFiles, const ArgsManager& args); } // namespace node #endif // BITCOIN_NODE_BLOCKSTORAGE_H diff --git a/src/validation.cpp b/src/validation.cpp index bc9b2acbbf10..823c2ca5d354 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -53,7 +53,6 @@ #include #include #include -#include #include #include #include @@ -138,6 +137,13 @@ int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE; uint256 hashAssumeValid; arith_uint256 nMinimumChainWork; +// Forward declaration to break dependency over node/transaction.h +namespace node +{ +CTransactionRef GetTransaction(const CBlockIndex* const block_index, const CTxMemPool* const mempool, const uint256& hash, const Consensus::Params& consensusParams, uint256& hashBlock); +} // namespace node +using node::GetTransaction; + const CBlockIndex* CChainState::FindForkInGlobalIndex(const CBlockLocator& locator) const { AssertLockHeld(cs_main); @@ -752,7 +758,8 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws) if (auto conflictLockOpt = m_chain_helper.ConflictingISLockIfAny(tx); conflictLockOpt.has_value()) { auto& [_, conflict_txid] = conflictLockOpt.value(); - if (auto [txConflict, _] = GetTransactionBlock(conflict_txid, &m_pool); txConflict) { + uint256 hashBlock; + if (auto txConflict = GetTransaction(nullptr, &m_pool, conflict_txid, chainparams.GetConsensus(), hashBlock); txConflict) { GetMainSignals().NotifyInstantSendDoubleSpendAttempt(ptx, txConflict); } LogPrintf("ERROR: AcceptToMemoryPool : Transaction %s conflicts with locked TX %s\n", hash.ToString(), conflict_txid.ToString()); diff --git a/test/lint/lint-circular-dependencies.py b/test/lint/lint-circular-dependencies.py index 5c96da1e7298..a1d7ef640e33 100755 --- a/test/lint/lint-circular-dependencies.py +++ b/test/lint/lint-circular-dependencies.py @@ -35,24 +35,17 @@ "consensus/tx_verify -> evo/assetlocktx -> llmq/commitment -> validation -> consensus/tx_verify", "consensus/tx_verify -> evo/assetlocktx -> llmq/signing -> net_processing -> txmempool -> consensus/tx_verify", "core_io -> evo/cbtx -> evo/simplifiedmns -> core_io", - "dsnotificationinterface -> llmq/chainlocks -> node/blockstorage -> dsnotificationinterface", "evo/assetlocktx -> llmq/signing -> net_processing -> txmempool -> evo/assetlocktx", "evo/cbtx -> evo/simplifiedmns -> evo/cbtx", - "evo/chainhelper -> evo/specialtxman -> evo/deterministicmns -> evo/chainhelper", "evo/chainhelper -> evo/specialtxman -> validation -> evo/chainhelper", - "evo/chainhelper -> llmq/chainlocks -> evo/chainhelper", - "evo/chainhelper -> llmq/instantsend -> evo/chainhelper", - "evo/chainhelper -> masternode/payments -> governance/classes -> governance/object -> evo/chainhelper", - "evo/chainhelper -> node/transaction -> node/context -> evo/chainhelper", + "evo/deterministicmns -> index/txindex -> validation -> evo/deterministicmns", + "evo/deterministicmns -> index/txindex -> validation -> txmempool -> evo/deterministicmns", "evo/deterministicmns -> llmq/commitment -> evo/deterministicmns", - "evo/deterministicmns -> llmq/commitment -> validation -> evo/deterministicmns", - "evo/deterministicmns -> llmq/commitment -> validation -> txmempool -> evo/deterministicmns", "evo/deterministicmns -> llmq/utils -> evo/deterministicmns", "evo/deterministicmns -> llmq/utils -> llmq/snapshot -> evo/simplifiedmns -> evo/deterministicmns", "evo/deterministicmns -> llmq/utils -> net -> evo/deterministicmns", "evo/deterministicmns -> validationinterface -> evo/deterministicmns", "evo/deterministicmns -> validationinterface -> governance/vote -> evo/deterministicmns", - "evo/mnhftx -> validation -> evo/mnhftx", "evo/simplifiedmns -> llmq/blockprocessor -> llmq/utils -> llmq/snapshot -> evo/simplifiedmns", "evo/specialtxman -> validation -> evo/specialtxman", "governance/governance -> governance/object -> governance/governance",