diff --git a/src/coinjoin/client.cpp b/src/coinjoin/client.cpp index a25f32510d513..4858223e07cce 100644 --- a/src/coinjoin/client.cpp +++ b/src/coinjoin/client.cpp @@ -166,6 +166,7 @@ void CCoinJoinClientManager::ProcessMessage(CNode& peer, CChainState& active_cha CCoinJoinClientSession::CCoinJoinClientSession(const std::shared_ptr& wallet, CoinJoinWalletManager& walletman, CCoinJoinClientManager& clientman, CDeterministicMNManager& dmnman, CMasternodeMetaMan& mn_metaman, const CMasternodeSync& mn_sync, + const llmq::CInstantSendManager& isman, const std::unique_ptr& queueman, bool is_masternode) : m_wallet(wallet), @@ -174,6 +175,7 @@ CCoinJoinClientSession::CCoinJoinClientSession(const std::shared_ptr& w m_dmnman(dmnman), m_mn_metaman(mn_metaman), m_mn_sync(mn_sync), + m_isman{isman}, m_queueman(queueman), m_is_masternode{is_masternode} {} @@ -589,7 +591,8 @@ bool CCoinJoinClientSession::SignFinalTransaction(CNode& peer, CChainState& acti // Make sure all inputs/outputs are valid PoolMessage nMessageID{MSG_NOERR}; - if (!IsValidInOuts(active_chainstate, mempool, finalMutableTransaction.vin, finalMutableTransaction.vout, nMessageID, nullptr)) { + if (!IsValidInOuts(active_chainstate, m_isman, mempool, finalMutableTransaction.vin, finalMutableTransaction.vout, + nMessageID, nullptr)) { WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- ERROR! IsValidInOuts() failed: %s\n", __func__, CoinJoin::GetMessageByID(nMessageID).translated); UnlockCoins(); keyHolderStorage.ReturnAll(); @@ -953,7 +956,7 @@ bool CCoinJoinClientSession::DoAutomaticDenominating(ChainstateManager& chainman return false; } } else { - if (!CoinJoin::IsCollateralValid(chainman, mempool, CTransaction(txMyCollateral))) { + if (!CoinJoin::IsCollateralValid(chainman, m_isman, mempool, CTransaction(txMyCollateral))) { WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::DoAutomaticDenominating -- invalid collateral, recreating...\n"); if (!CreateCollateralTransaction(txMyCollateral, strReason)) { WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::DoAutomaticDenominating -- create collateral error: %s\n", strReason); @@ -1012,7 +1015,7 @@ bool CCoinJoinClientManager::DoAutomaticDenominating(ChainstateManager& chainman AssertLockNotHeld(cs_deqsessions); LOCK(cs_deqsessions); if (int(deqSessions.size()) < CCoinJoinClientOptions::GetSessions()) { - deqSessions.emplace_back(m_wallet, m_walletman, *this, m_dmnman, m_mn_metaman, m_mn_sync, m_queueman, + deqSessions.emplace_back(m_wallet, m_walletman, *this, m_dmnman, m_mn_metaman, m_mn_sync, m_isman, m_queueman, m_is_masternode); } for (auto& session : deqSessions) { @@ -1915,7 +1918,8 @@ void CoinJoinWalletManager::Add(const std::shared_ptr& wallet) LOCK(cs_wallet_manager_map); m_wallet_manager_map.try_emplace(wallet->GetName(), std::make_unique(wallet, *this, m_dmnman, m_mn_metaman, - m_mn_sync, m_queueman, m_is_masternode)); + m_mn_sync, m_isman, m_queueman, + m_is_masternode)); } g_wallet_init_interface.InitCoinJoinSettings(*this); } diff --git a/src/coinjoin/client.h b/src/coinjoin/client.h index 2eccc1cfc28cc..da8f850c923c1 100644 --- a/src/coinjoin/client.h +++ b/src/coinjoin/client.h @@ -77,13 +77,14 @@ class CoinJoinWalletManager { public: CoinJoinWalletManager(ChainstateManager& chainman, CDeterministicMNManager& dmnman, CMasternodeMetaMan& mn_metaman, - const CTxMemPool& mempool, const CMasternodeSync& mn_sync, + const CTxMemPool& mempool, const CMasternodeSync& mn_sync, const llmq::CInstantSendManager& isman, const std::unique_ptr& queueman, bool is_masternode) : m_chainman(chainman), m_dmnman(dmnman), m_mn_metaman(mn_metaman), m_mempool(mempool), m_mn_sync(mn_sync), + m_isman{isman}, m_queueman(queueman), m_is_masternode{is_masternode} {} @@ -125,6 +126,7 @@ class CoinJoinWalletManager { CMasternodeMetaMan& m_mn_metaman; const CTxMemPool& m_mempool; const CMasternodeSync& m_mn_sync; + const llmq::CInstantSendManager& m_isman; const std::unique_ptr& m_queueman; const bool m_is_masternode; @@ -142,6 +144,7 @@ class CCoinJoinClientSession : public CCoinJoinBaseSession CDeterministicMNManager& m_dmnman; CMasternodeMetaMan& m_mn_metaman; const CMasternodeSync& m_mn_sync; + const llmq::CInstantSendManager& m_isman; const std::unique_ptr& m_queueman; // Track node type @@ -201,6 +204,7 @@ class CCoinJoinClientSession : public CCoinJoinBaseSession explicit CCoinJoinClientSession(const std::shared_ptr& wallet, CoinJoinWalletManager& walletman, CCoinJoinClientManager& clientman, CDeterministicMNManager& dmnman, CMasternodeMetaMan& mn_metaman, const CMasternodeSync& mn_sync, + const llmq::CInstantSendManager& isman, const std::unique_ptr& queueman, bool is_masternode); void ProcessMessage(CNode& peer, CChainState& active_chainstate, CConnman& connman, const CTxMemPool& mempool, std::string_view msg_type, CDataStream& vRecv); @@ -266,6 +270,7 @@ class CCoinJoinClientManager CDeterministicMNManager& m_dmnman; CMasternodeMetaMan& m_mn_metaman; const CMasternodeSync& m_mn_sync; + const llmq::CInstantSendManager& m_isman; const std::unique_ptr& m_queueman; // Track node type @@ -302,13 +307,14 @@ class CCoinJoinClientManager explicit CCoinJoinClientManager(const std::shared_ptr& wallet, CoinJoinWalletManager& walletman, CDeterministicMNManager& dmnman, CMasternodeMetaMan& mn_metaman, - const CMasternodeSync& mn_sync, + const CMasternodeSync& mn_sync, const llmq::CInstantSendManager& isman, const std::unique_ptr& queueman, bool is_masternode) : m_wallet(wallet), m_walletman(walletman), m_dmnman(dmnman), m_mn_metaman(mn_metaman), m_mn_sync(mn_sync), + m_isman{isman}, m_queueman(queueman), m_is_masternode{is_masternode} { diff --git a/src/coinjoin/coinjoin.cpp b/src/coinjoin/coinjoin.cpp index 74fc644a70911..c4282f0f69de7 100644 --- a/src/coinjoin/coinjoin.cpp +++ b/src/coinjoin/coinjoin.cpp @@ -207,7 +207,10 @@ std::string CCoinJoinBaseSession::GetStateString() const } } -bool CCoinJoinBaseSession::IsValidInOuts(CChainState& active_chainstate, const CTxMemPool& mempool, const std::vector& vin, const std::vector& vout, PoolMessage& nMessageIDRet, bool* fConsumeCollateralRet) const +bool CCoinJoinBaseSession::IsValidInOuts(CChainState& active_chainstate, const llmq::CInstantSendManager& isman, + const CTxMemPool& mempool, const std::vector& vin, + const std::vector& vout, PoolMessage& nMessageIDRet, + bool* fConsumeCollateralRet) const { std::set setScripPubKeys; nMessageIDRet = MSG_NOERR; @@ -268,7 +271,7 @@ bool CCoinJoinBaseSession::IsValidInOuts(CChainState& active_chainstate, const C Coin coin; if (!viewMemPool.GetCoin(txin.prevout, coin) || coin.IsSpent() || - (coin.nHeight == MEMPOOL_HEIGHT && !llmq::quorumInstantSendManager->IsLocked(txin.prevout.hash))) { + (coin.nHeight == MEMPOOL_HEIGHT && !isman.IsLocked(txin.prevout.hash))) { LogPrint(BCLog::COINJOIN, "CCoinJoinBaseSession::%s -- ERROR: missing, spent or non-locked mempool input! txin=%s\n", __func__, txin.ToString()); nMessageIDRet = ERR_MISSING_TX; return false; @@ -313,7 +316,8 @@ bool ATMPIfSaneFee(ChainstateManager& chainman, const CTransactionRef& tx, bool } // check to make sure the collateral provided by the client is valid -bool CoinJoin::IsCollateralValid(ChainstateManager& chainman, const CTxMemPool& mempool, const CTransaction& txCollateral) +bool CoinJoin::IsCollateralValid(ChainstateManager& chainman, const llmq::CInstantSendManager& isman, + const CTxMemPool& mempool, const CTransaction& txCollateral) { if (txCollateral.vout.empty()) return false; if (txCollateral.nLockTime != 0) return false; @@ -334,7 +338,7 @@ bool CoinJoin::IsCollateralValid(ChainstateManager& chainman, const CTxMemPool& Coin coin; auto mempoolTx = mempool.get(txin.prevout.hash); if (mempoolTx != nullptr) { - if (mempool.isSpent(txin.prevout) || !llmq::quorumInstantSendManager->IsLocked(txin.prevout.hash)) { + if (mempool.isSpent(txin.prevout) || !isman.IsLocked(txin.prevout.hash)) { LogPrint(BCLog::COINJOIN, "CoinJoin::IsCollateralValid -- spent or non-locked mempool input! txin=%s\n", txin.ToString()); return false; } diff --git a/src/coinjoin/coinjoin.h b/src/coinjoin/coinjoin.h index 68e2f40c05549..3d5e1f8022dde 100644 --- a/src/coinjoin/coinjoin.h +++ b/src/coinjoin/coinjoin.h @@ -33,6 +33,7 @@ class TxValidationState; namespace llmq { class CChainLocksHandler; +class CInstantSendManager; } // namespace llmq extern RecursiveMutex cs_main; @@ -308,7 +309,9 @@ class CCoinJoinBaseSession virtual void SetNull() EXCLUSIVE_LOCKS_REQUIRED(cs_coinjoin); - bool IsValidInOuts(CChainState& active_chainstate, const CTxMemPool& mempool, const std::vector& vin, const std::vector& vout, PoolMessage& nMessageIDRet, bool* fConsumeCollateralRet) const; + bool IsValidInOuts(CChainState& active_chainstate, const llmq::CInstantSendManager& isman, + const CTxMemPool& mempool, const std::vector& vin, const std::vector& vout, + PoolMessage& nMessageIDRet, bool* fConsumeCollateralRet) const; public: int nSessionDenom{0}; // Users must submit a denom matching this @@ -365,7 +368,8 @@ namespace CoinJoin constexpr CAmount GetMaxPoolAmount() { return COINJOIN_ENTRY_MAX_SIZE * vecStandardDenominations.front(); } /// If the collateral is valid given by a client - bool IsCollateralValid(ChainstateManager& chainman, const CTxMemPool& mempool, const CTransaction& txCollateral); + bool IsCollateralValid(ChainstateManager& chainman, const llmq::CInstantSendManager& isman, + const CTxMemPool& mempool, const CTransaction& txCollateral); } class CDSTXManager diff --git a/src/coinjoin/context.cpp b/src/coinjoin/context.cpp index 8ab6f9e6360ae..0bd9da7c9d4c5 100644 --- a/src/coinjoin/context.cpp +++ b/src/coinjoin/context.cpp @@ -12,17 +12,17 @@ CJContext::CJContext(ChainstateManager& chainman, CConnman& connman, CDeterministicMNManager& dmnman, CMasternodeMetaMan& mn_metaman, CTxMemPool& mempool, const CActiveMasternodeManager* const mn_activeman, const CMasternodeSync& mn_sync, - std::unique_ptr& peerman, bool relay_txes) : + const llmq::CInstantSendManager& isman, std::unique_ptr& peerman, bool relay_txes) : dstxman{std::make_unique()}, #ifdef ENABLE_WALLET - walletman{std::make_unique(chainman, dmnman, mn_metaman, mempool, mn_sync, queueman, + walletman{std::make_unique(chainman, dmnman, mn_metaman, mempool, mn_sync, isman, queueman, /*is_masternode=*/mn_activeman != nullptr)}, queueman{relay_txes ? std::make_unique(*walletman, dmnman, mn_metaman, mn_sync, /*is_masternode=*/mn_activeman != nullptr) : nullptr}, #endif // ENABLE_WALLET server{std::make_unique(chainman, connman, dmnman, *dstxman, mn_metaman, mempool, mn_activeman, - mn_sync, peerman)} + mn_sync, isman, peerman)} {} CJContext::~CJContext() {} diff --git a/src/coinjoin/context.h b/src/coinjoin/context.h index b4e8c6a47f557..0fad302749e9d 100644 --- a/src/coinjoin/context.h +++ b/src/coinjoin/context.h @@ -22,6 +22,9 @@ class CMasternodeMetaMan; class CMasternodeSync; class CTxMemPool; class PeerManager; +namespace llmq { +class CInstantSendManager; +}; #ifdef ENABLE_WALLET class CCoinJoinClientQueueManager; @@ -33,7 +36,8 @@ struct CJContext { CJContext(const CJContext&) = delete; CJContext(ChainstateManager& chainman, CConnman& connman, CDeterministicMNManager& dmnman, CMasternodeMetaMan& mn_metaman, CTxMemPool& mempool, const CActiveMasternodeManager* const mn_activeman, - const CMasternodeSync& mn_sync, std::unique_ptr& peerman, bool relay_txes); + const CMasternodeSync& mn_sync, const llmq::CInstantSendManager& isman, + std::unique_ptr& peerman, bool relay_txes); ~CJContext(); const std::unique_ptr dstxman; diff --git a/src/coinjoin/server.cpp b/src/coinjoin/server.cpp index 6e0ee38474b7f..ac9acd40bbef4 100644 --- a/src/coinjoin/server.cpp +++ b/src/coinjoin/server.cpp @@ -583,7 +583,7 @@ bool CCoinJoinServer::AddEntry(const CCoinJoinEntry& entry, PoolMessage& nMessag return false; } - if (!CoinJoin::IsCollateralValid(m_chainman, mempool, *entry.txCollateral)) { + if (!CoinJoin::IsCollateralValid(m_chainman, m_isman, mempool, *entry.txCollateral)) { LogPrint(BCLog::COINJOIN, "CCoinJoinServer::%s -- ERROR: collateral not valid!\n", __func__); nMessageIDRet = ERR_INVALID_COLLATERAL; return false; @@ -617,7 +617,8 @@ bool CCoinJoinServer::AddEntry(const CCoinJoinEntry& entry, PoolMessage& nMessag } bool fConsumeCollateral{false}; - if (!IsValidInOuts(m_chainman.ActiveChainstate(), mempool, vin, entry.vecTxOut, nMessageIDRet, &fConsumeCollateral)) { + if (!IsValidInOuts(m_chainman.ActiveChainstate(), m_isman, mempool, vin, entry.vecTxOut, nMessageIDRet, + &fConsumeCollateral)) { LogPrint(BCLog::COINJOIN, "CCoinJoinServer::%s -- ERROR! IsValidInOuts() failed: %s\n", __func__, CoinJoin::GetMessageByID(nMessageIDRet).translated); if (fConsumeCollateral) { ConsumeCollateral(entry.txCollateral); @@ -694,7 +695,7 @@ bool CCoinJoinServer::IsAcceptableDSA(const CCoinJoinAccept& dsa, PoolMessage& n } // check collateral - if (!fUnitTest && !CoinJoin::IsCollateralValid(m_chainman, mempool, CTransaction(dsa.txCollateral))) { + if (!fUnitTest && !CoinJoin::IsCollateralValid(m_chainman, m_isman, mempool, CTransaction(dsa.txCollateral))) { LogPrint(BCLog::COINJOIN, "CCoinJoinServer::%s -- collateral not valid!\n", __func__); nMessageIDRet = ERR_INVALID_COLLATERAL; return false; diff --git a/src/coinjoin/server.h b/src/coinjoin/server.h index c33e98fbf8e70..f7048816ba840 100644 --- a/src/coinjoin/server.h +++ b/src/coinjoin/server.h @@ -36,6 +36,7 @@ class CCoinJoinServer : public CCoinJoinBaseSession, public CCoinJoinBaseManager CTxMemPool& mempool; const CActiveMasternodeManager* const m_mn_activeman; const CMasternodeSync& m_mn_sync; + const llmq::CInstantSendManager& m_isman; std::unique_ptr& m_peerman; // Mixing uses collateral transactions to trust parties entering the pool @@ -94,7 +95,7 @@ class CCoinJoinServer : public CCoinJoinBaseSession, public CCoinJoinBaseManager explicit CCoinJoinServer(ChainstateManager& chainman, CConnman& _connman, CDeterministicMNManager& dmnman, CDSTXManager& dstxman, CMasternodeMetaMan& mn_metaman, CTxMemPool& mempool, const CActiveMasternodeManager* const mn_activeman, const CMasternodeSync& mn_sync, - std::unique_ptr& peerman) : + const llmq::CInstantSendManager& isman, std::unique_ptr& peerman) : m_chainman(chainman), connman(_connman), m_dmnman(dmnman), @@ -103,6 +104,7 @@ class CCoinJoinServer : public CCoinJoinBaseSession, public CCoinJoinBaseManager mempool(mempool), m_mn_activeman(mn_activeman), m_mn_sync(mn_sync), + m_isman{isman}, m_peerman(peerman), vecSessionCollaterals(), fUnitTest(false) diff --git a/src/dsnotificationinterface.cpp b/src/dsnotificationinterface.cpp index 3f412026f8582..86965e1380fe7 100644 --- a/src/dsnotificationinterface.cpp +++ b/src/dsnotificationinterface.cpp @@ -91,7 +91,7 @@ void CDSNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, con #endif // ENABLE_WALLET m_llmq_ctx->isman->UpdatedBlockTip(pindexNew); - m_llmq_ctx->clhandler->UpdatedBlockTip(); + m_llmq_ctx->clhandler->UpdatedBlockTip(*m_llmq_ctx->isman); m_llmq_ctx->qman->UpdatedBlockTip(pindexNew, m_connman, fInitialDownload); m_llmq_ctx->qdkgsman->UpdatedBlockTip(pindexNew, fInitialDownload); diff --git a/src/evo/cbtx.cpp b/src/evo/cbtx.cpp index fc08bd5db57fd..fca6a504032b8 100644 --- a/src/evo/cbtx.cpp +++ b/src/evo/cbtx.cpp @@ -62,8 +62,8 @@ bool CheckCbTx(const CTransaction& tx, const CBlockIndex* pindexPrev, TxValidati // This can only be done after the block has been fully processed, as otherwise we won't have the finished MN list bool CheckCbTxMerkleRoots(const CBlock& block, const CBlockIndex* pindex, CDeterministicMNManager& dmnman, - const llmq::CQuorumBlockProcessor& quorum_block_processor, BlockValidationState& state, - const CCoinsViewCache& view) + llmq::CQuorumSnapshotManager& qsnapman, const llmq::CQuorumBlockProcessor& quorum_block_processor, + BlockValidationState& state, const CCoinsViewCache& view) { if (block.vtx[0]->nType != TRANSACTION_COINBASE) { return true; @@ -87,7 +87,7 @@ bool CheckCbTxMerkleRoots(const CBlock& block, const CBlockIndex* pindex, CDeter static int64_t nTimeMerkleQuorum = 0; uint256 calculatedMerkleRoot; - if (!CalcCbTxMerkleRootMNList(block, pindex->pprev, calculatedMerkleRoot, dmnman, state, view)) { + if (!CalcCbTxMerkleRootMNList(block, pindex->pprev, calculatedMerkleRoot, state, dmnman, qsnapman, view)) { // pass the state returned by the function above return false; } @@ -117,7 +117,8 @@ bool CheckCbTxMerkleRoots(const CBlock& block, const CBlockIndex* pindex, CDeter } bool CalcCbTxMerkleRootMNList(const CBlock& block, const CBlockIndex* pindexPrev, uint256& merkleRootRet, - CDeterministicMNManager& dmnman, BlockValidationState& state, const CCoinsViewCache& view) + BlockValidationState& state, CDeterministicMNManager& dmnman, + llmq::CQuorumSnapshotManager& qsnapman, const CCoinsViewCache& view) { try { static std::atomic nTimeDMN = 0; @@ -127,7 +128,7 @@ bool CalcCbTxMerkleRootMNList(const CBlock& block, const CBlockIndex* pindexPrev int64_t nTime1 = GetTimeMicros(); CDeterministicMNList tmpMNList; - if (!dmnman.BuildNewListFromBlock(block, pindexPrev, state, view, tmpMNList, false)) { + if (!dmnman.BuildNewListFromBlock(block, pindexPrev, state, view, tmpMNList, qsnapman, false)) { // pass the state returned by the function above return false; } diff --git a/src/evo/cbtx.h b/src/evo/cbtx.h index ad6b74d10fb90..ae29f2fc700de 100644 --- a/src/evo/cbtx.h +++ b/src/evo/cbtx.h @@ -19,8 +19,9 @@ class CDeterministicMNManager; class TxValidationState; namespace llmq { -class CQuorumBlockProcessor; class CChainLocksHandler; +class CQuorumBlockProcessor; +class CQuorumSnapshotManager; }// namespace llmq // Forward declaration from core_io to get rid of circular dependency @@ -87,10 +88,11 @@ template<> struct is_serializable_enum : std::true_type {}; bool CheckCbTx(const CTransaction& tx, const CBlockIndex* pindexPrev, TxValidationState& state); bool CheckCbTxMerkleRoots(const CBlock& block, const CBlockIndex* pindex, CDeterministicMNManager& dmnman, - const llmq::CQuorumBlockProcessor& quorum_block_processor, BlockValidationState& state, - const CCoinsViewCache& view); + llmq::CQuorumSnapshotManager& qsnapman, const llmq::CQuorumBlockProcessor& quorum_block_processor, + BlockValidationState& state, const CCoinsViewCache& view); bool CalcCbTxMerkleRootMNList(const CBlock& block, const CBlockIndex* pindexPrev, uint256& merkleRootRet, - CDeterministicMNManager& dmnman, BlockValidationState& state, const CCoinsViewCache& view); + BlockValidationState& state, CDeterministicMNManager& dmnman, + llmq::CQuorumSnapshotManager& qsnapman, const CCoinsViewCache& view); bool CalcCbTxMerkleRootQuorums(const CBlock& block, const CBlockIndex* pindexPrev, const llmq::CQuorumBlockProcessor& quorum_block_processor, uint256& merkleRootRet, BlockValidationState& state); diff --git a/src/evo/chainhelper.cpp b/src/evo/chainhelper.cpp index 4c6a6ab964694..f2a042bd984a4 100644 --- a/src/evo/chainhelper.cpp +++ b/src/evo/chainhelper.cpp @@ -6,14 +6,55 @@ #include #include +#include +#include #include -CChainstateHelper::CChainstateHelper(CCreditPoolManager& cpoolman, CDeterministicMNManager& dmnman, CMNHFManager& mnhfman, CGovernanceManager& govman, - llmq::CQuorumBlockProcessor& qblockman, const ChainstateManager& chainman, const Consensus::Params& consensus_params, - const CMasternodeSync& mn_sync, const CSporkManager& sporkman, const llmq::CChainLocksHandler& clhandler, - const llmq::CQuorumManager& qman) - : mn_payments{std::make_unique(dmnman, govman, chainman, consensus_params, mn_sync, sporkman)}, - special_tx{std::make_unique(cpoolman, dmnman, mnhfman, qblockman, chainman, consensus_params, clhandler, qman)} +CChainstateHelper::CChainstateHelper(CCreditPoolManager& cpoolman, CDeterministicMNManager& dmnman, + CMNHFManager& mnhfman, CGovernanceManager& govman, llmq::CInstantSendManager& isman, + llmq::CQuorumBlockProcessor& qblockman, llmq::CQuorumSnapshotManager& qsnapman, + const ChainstateManager& chainman, const Consensus::Params& consensus_params, + const CMasternodeSync& mn_sync, const CSporkManager& sporkman, + const llmq::CChainLocksHandler& clhandler, const llmq::CQuorumManager& qman) : + isman{isman}, + clhandler{clhandler}, + mn_payments{std::make_unique(dmnman, govman, chainman, consensus_params, mn_sync, sporkman)}, + special_tx{std::make_unique(cpoolman, dmnman, mnhfman, qblockman, qsnapman, chainman, + consensus_params, clhandler, qman)} {} CChainstateHelper::~CChainstateHelper() = default; + +/** Passthrough functions to CChainLocksHandler */ +bool CChainstateHelper::HasConflictingChainLock(int nHeight, const uint256& blockHash) const +{ + return clhandler.HasConflictingChainLock(nHeight, blockHash); +} + +bool CChainstateHelper::HasChainLock(int nHeight, const uint256& blockHash) const +{ + return clhandler.HasChainLock(nHeight, blockHash); +} + +int32_t CChainstateHelper::GetBestChainLockHeight() const { return clhandler.GetBestChainLock().getHeight(); } + +/** Passthrough functions to CInstantSendManager */ +std::optional> CChainstateHelper::ConflictingISLockIfAny( + const CTransaction& tx) const +{ + const auto islock = isman.GetConflictingLock(tx); + if (!islock) return std::nullopt; + return std::make_pair(::SerializeHash(*islock), islock->txid); +} + +bool CChainstateHelper::IsInstantSendWaitingForTx(const uint256& hash) const { return isman.IsWaitingForTx(hash); } + +bool CChainstateHelper::RemoveConflictingISLockByTx(const CTransaction& tx) +{ + const auto islock = isman.GetConflictingLock(tx); + if (!islock) return false; + isman.RemoveConflictingLock(::SerializeHash(*islock), *islock); + return true; +} + +bool CChainstateHelper::ShouldInstantSendRejectConflicts() const { return isman.RejectConflictingBlocks(); } diff --git a/src/evo/chainhelper.h b/src/evo/chainhelper.h index 73db5b3427e6a..82b6597e3af6d 100644 --- a/src/evo/chainhelper.h +++ b/src/evo/chainhelper.h @@ -6,6 +6,7 @@ #define BITCOIN_EVO_CHAINHELPER_H #include +#include class CCreditPoolManager; class CDeterministicMNManager; @@ -16,26 +17,47 @@ class CMasternodeSync; class CGovernanceManager; class CSpecialTxProcessor; class CSporkManager; +class CTransaction; +class uint256; namespace Consensus { struct Params; } namespace llmq { class CChainLocksHandler; +class CInstantSendManager; class CQuorumBlockProcessor; class CQuorumManager; +class CQuorumSnapshotManager; } class CChainstateHelper { +private: + llmq::CInstantSendManager& isman; + const llmq::CChainLocksHandler& clhandler; + public: - explicit CChainstateHelper(CCreditPoolManager& cpoolman, CDeterministicMNManager& dmnman, CMNHFManager& mnhfman, CGovernanceManager& govman, - llmq::CQuorumBlockProcessor& qblockman, const ChainstateManager& chainman, const Consensus::Params& consensus_params, - const CMasternodeSync& mn_sync, const CSporkManager& sporkman, const llmq::CChainLocksHandler& clhandler, - const llmq::CQuorumManager& qman); + explicit CChainstateHelper(CCreditPoolManager& cpoolman, CDeterministicMNManager& dmnman, CMNHFManager& mnhfman, + CGovernanceManager& govman, llmq::CInstantSendManager& isman, + llmq::CQuorumBlockProcessor& qblockman, llmq::CQuorumSnapshotManager& qsnapman, + const ChainstateManager& chainman, const Consensus::Params& consensus_params, + const CMasternodeSync& mn_sync, const CSporkManager& sporkman, + const llmq::CChainLocksHandler& clhandler, const llmq::CQuorumManager& qman); ~CChainstateHelper(); CChainstateHelper() = delete; CChainstateHelper(const CChainstateHelper&) = delete; + /** Passthrough functions to CChainLocksHandler */ + bool HasConflictingChainLock(int nHeight, const uint256& blockHash) const; + bool HasChainLock(int nHeight, const uint256& blockHash) const; + int32_t GetBestChainLockHeight() const; + + /** Passthrough functions to CInstantSendManager */ + std::optional> ConflictingISLockIfAny(const CTransaction& tx) const; + bool IsInstantSendWaitingForTx(const uint256& hash) const; + bool RemoveConflictingISLockByTx(const CTransaction& tx); + bool ShouldInstantSendRejectConflicts() const; + public: const std::unique_ptr mn_payments; const std::unique_ptr special_tx; diff --git a/src/evo/deterministicmns.cpp b/src/evo/deterministicmns.cpp index 96fbe4c02cf02..f997859eddcd8 100644 --- a/src/evo/deterministicmns.cpp +++ b/src/evo/deterministicmns.cpp @@ -595,7 +595,10 @@ void CDeterministicMNList::RemoveMN(const uint256& proTxHash) mnInternalIdMap = mnInternalIdMap.erase(dmn->GetInternalId()); } -bool CDeterministicMNManager::ProcessBlock(const CBlock& block, gsl::not_null pindex, BlockValidationState& state, const CCoinsViewCache& view, bool fJustCheck, std::optional& updatesRet) +bool CDeterministicMNManager::ProcessBlock(const CBlock& block, gsl::not_null pindex, + BlockValidationState& state, const CCoinsViewCache& view, + llmq::CQuorumSnapshotManager& qsnapman, bool fJustCheck, + std::optional& updatesRet) { AssertLockHeld(cs_main); @@ -610,7 +613,7 @@ bool CDeterministicMNManager::ProcessBlock(const CBlock& block, gsl::not_nullnHeight; try { - if (!BuildNewListFromBlock(block, pindex->pprev, state, view, newList, true)) { + if (!BuildNewListFromBlock(block, pindex->pprev, state, view, newList, qsnapman, true)) { // pass the state returned by the function above return false; } @@ -700,7 +703,10 @@ void CDeterministicMNManager::UpdatedBlockTip(gsl::not_null tipIndex = pindex; } -bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::not_null pindexPrev, BlockValidationState& state, const CCoinsViewCache& view, CDeterministicMNList& mnListRet, bool debugLogs) +bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::not_null pindexPrev, + BlockValidationState& state, const CCoinsViewCache& view, + CDeterministicMNList& mnListRet, + llmq::CQuorumSnapshotManager& qsnapman, bool debugLogs) { int nHeight = pindexPrev->nHeight + 1; @@ -923,7 +929,7 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::no return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-qc-quorum-hash"); } - HandleQuorumCommitment(opt_qc->commitment, pQuorumBaseBlockIndex, newList, debugLogs); + HandleQuorumCommitment(opt_qc->commitment, pQuorumBaseBlockIndex, newList, qsnapman, debugLogs); } } } @@ -995,11 +1001,14 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::no return true; } -void CDeterministicMNManager::HandleQuorumCommitment(const llmq::CFinalCommitment& qc, gsl::not_null pQuorumBaseBlockIndex, CDeterministicMNList& mnList, bool debugLogs) +void CDeterministicMNManager::HandleQuorumCommitment(const llmq::CFinalCommitment& qc, + gsl::not_null pQuorumBaseBlockIndex, + CDeterministicMNList& mnList, + llmq::CQuorumSnapshotManager& qsnapman, bool debugLogs) { // The commitment has already been validated at this point, so it's safe to use members of it - auto members = llmq::utils::GetAllQuorumMembers(qc.llmqType, *this, pQuorumBaseBlockIndex); + auto members = llmq::utils::GetAllQuorumMembers(qc.llmqType, *this, qsnapman, pQuorumBaseBlockIndex); for (size_t i = 0; i < members.size(); i++) { if (!mnList.HasMN(members[i]->proTxHash)) { diff --git a/src/evo/deterministicmns.h b/src/evo/deterministicmns.h index 81621d8bd9863..0fde8da19b7ec 100644 --- a/src/evo/deterministicmns.h +++ b/src/evo/deterministicmns.h @@ -35,9 +35,9 @@ class TxValidationState; extern RecursiveMutex cs_main; -namespace llmq -{ - class CFinalCommitment; +namespace llmq { +class CFinalCommitment; +class CQuorumSnapshotManager; } // namespace llmq class CDeterministicMN @@ -598,15 +598,18 @@ class CDeterministicMNManager ~CDeterministicMNManager() = default; bool ProcessBlock(const CBlock& block, gsl::not_null pindex, BlockValidationState& state, - const CCoinsViewCache& view, bool fJustCheck, std::optional& updatesRet) EXCLUSIVE_LOCKS_REQUIRED(!cs, cs_main); + const CCoinsViewCache& view, llmq::CQuorumSnapshotManager& qsnapman, bool fJustCheck, + std::optional& updatesRet) EXCLUSIVE_LOCKS_REQUIRED(!cs, cs_main); bool UndoBlock(gsl::not_null pindex, std::optional& updatesRet) EXCLUSIVE_LOCKS_REQUIRED(!cs); void UpdatedBlockTip(gsl::not_null pindex) EXCLUSIVE_LOCKS_REQUIRED(!cs); // the returned list will not contain the correct block hash (we can't know it yet as the coinbase TX is not updated yet) - bool BuildNewListFromBlock(const CBlock& block, gsl::not_null pindexPrev, BlockValidationState& state, const CCoinsViewCache& view, - CDeterministicMNList& mnListRet, bool debugLogs) EXCLUSIVE_LOCKS_REQUIRED(!cs); - void HandleQuorumCommitment(const llmq::CFinalCommitment& qc, gsl::not_null pQuorumBaseBlockIndex, CDeterministicMNList& mnList, bool debugLogs); + bool BuildNewListFromBlock(const CBlock& block, gsl::not_null pindexPrev, + BlockValidationState& state, const CCoinsViewCache& view, CDeterministicMNList& mnListRet, + llmq::CQuorumSnapshotManager& qsnapman, bool debugLogs) EXCLUSIVE_LOCKS_REQUIRED(!cs); + void HandleQuorumCommitment(const llmq::CFinalCommitment& qc, gsl::not_null pQuorumBaseBlockIndex, + CDeterministicMNList& mnList, llmq::CQuorumSnapshotManager& qsnapman, bool debugLogs); CDeterministicMNList GetListForBlock(gsl::not_null pindex) EXCLUSIVE_LOCKS_REQUIRED(!cs) { LOCK(cs); diff --git a/src/evo/specialtxman.cpp b/src/evo/specialtxman.cpp index 969efa2703055..9c74d35d4801f 100644 --- a/src/evo/specialtxman.cpp +++ b/src/evo/specialtxman.cpp @@ -19,10 +19,11 @@ #include #include -static bool CheckSpecialTxInner(CDeterministicMNManager& dmnman, const ChainstateManager& chainman, - const llmq::CQuorumManager& qman, const CTransaction& tx, const CBlockIndex* pindexPrev, - const CCoinsViewCache& view, const std::optional& indexes, bool check_sigs, - TxValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) +static bool CheckSpecialTxInner(CDeterministicMNManager& dmnman, llmq::CQuorumSnapshotManager& qsnapman, + const ChainstateManager& chainman, const llmq::CQuorumManager& qman, + const CTransaction& tx, const CBlockIndex* pindexPrev, const CCoinsViewCache& view, + const std::optional& indexes, bool check_sigs, TxValidationState& state) + EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { AssertLockHeld(cs_main); @@ -47,7 +48,7 @@ static bool CheckSpecialTxInner(CDeterministicMNManager& dmnman, const Chainstat case TRANSACTION_COINBASE: return CheckCbTx(tx, pindexPrev, state); case TRANSACTION_QUORUM_COMMITMENT: - return llmq::CheckLLMQCommitment(dmnman, chainman, tx, pindexPrev, state); + return llmq::CheckLLMQCommitment(dmnman, qsnapman, chainman, tx, pindexPrev, state); case TRANSACTION_MNHF_SIGNAL: return CheckMNHFTx(chainman, qman, tx, pindexPrev, state); case TRANSACTION_ASSET_LOCK: @@ -66,7 +67,8 @@ static bool CheckSpecialTxInner(CDeterministicMNManager& dmnman, const Chainstat bool CSpecialTxProcessor::CheckSpecialTx(const CTransaction& tx, const CBlockIndex* pindexPrev, const CCoinsViewCache& view, bool check_sigs, TxValidationState& state) { AssertLockHeld(cs_main); - return CheckSpecialTxInner(m_dmnman, m_chainman, m_qman, tx, pindexPrev, view, std::nullopt, check_sigs, state); + return CheckSpecialTxInner(m_dmnman, m_qsnapman, m_chainman, m_qman, tx, pindexPrev, view, std::nullopt, check_sigs, + state); } [[nodiscard]] bool CSpecialTxProcessor::ProcessSpecialTx(const CTransaction& tx, const CBlockIndex* pindex, TxValidationState& state) @@ -145,7 +147,8 @@ bool CSpecialTxProcessor::ProcessSpecialTxsInBlock(const CBlock& block, const CB TxValidationState tx_state; // At this moment CheckSpecialTx() and ProcessSpecialTx() may fail by 2 possible ways: // consensus failures and "TX_BAD_SPECIAL" - if (!CheckSpecialTxInner(m_dmnman, m_chainman, m_qman, *ptr_tx, pindex->pprev, view, creditPool.indexes, fCheckCbTxMerkleRoots, tx_state)) { + if (!CheckSpecialTxInner(m_dmnman, m_qsnapman, m_chainman, m_qman, *ptr_tx, pindex->pprev, view, + creditPool.indexes, fCheckCbTxMerkleRoots, tx_state)) { assert(tx_state.GetResult() == TxValidationResult::TX_CONSENSUS || tx_state.GetResult() == TxValidationResult::TX_BAD_SPECIAL); return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, tx_state.GetRejectReason(), strprintf("Special Transaction check failed (tx hash %s) %s", ptr_tx->GetHash().ToString(), tx_state.GetDebugMessage())); @@ -170,7 +173,7 @@ bool CSpecialTxProcessor::ProcessSpecialTxsInBlock(const CBlock& block, const CB nTimeQuorum += nTime3 - nTime2; LogPrint(BCLog::BENCHMARK, " - m_qblockman: %.2fms [%.2fs]\n", 0.001 * (nTime3 - nTime2), nTimeQuorum * 0.000001); - if (!m_dmnman.ProcessBlock(block, pindex, state, view, fJustCheck, updatesRet)) { + if (!m_dmnman.ProcessBlock(block, pindex, state, view, m_qsnapman, fJustCheck, updatesRet)) { // pass the state returned by the function above return false; } @@ -179,7 +182,7 @@ bool CSpecialTxProcessor::ProcessSpecialTxsInBlock(const CBlock& block, const CB nTimeDMN += nTime4 - nTime3; LogPrint(BCLog::BENCHMARK, " - m_dmnman: %.2fms [%.2fs]\n", 0.001 * (nTime4 - nTime3), nTimeDMN * 0.000001); - if (fCheckCbTxMerkleRoots && !CheckCbTxMerkleRoots(block, pindex, m_dmnman, m_qblockman, state, view)) { + if (fCheckCbTxMerkleRoots && !CheckCbTxMerkleRoots(block, pindex, m_dmnman, m_qsnapman, m_qblockman, state, view)) { // pass the state returned by the function above return false; } diff --git a/src/evo/specialtxman.h b/src/evo/specialtxman.h index c2148942a47d9..47dc319cb4e23 100644 --- a/src/evo/specialtxman.h +++ b/src/evo/specialtxman.h @@ -25,9 +25,10 @@ struct MNListUpdates; namespace Consensus { struct Params; } namespace llmq { +class CChainLocksHandler; class CQuorumBlockProcessor; class CQuorumManager; -class CChainLocksHandler; +class CQuorumSnapshotManager; } // namespace llmq extern RecursiveMutex cs_main; @@ -39,6 +40,7 @@ class CSpecialTxProcessor CDeterministicMNManager& m_dmnman; CMNHFManager& m_mnhfman; llmq::CQuorumBlockProcessor& m_qblockman; + llmq::CQuorumSnapshotManager& m_qsnapman; const ChainstateManager& m_chainman; const Consensus::Params& m_consensus_params; const llmq::CChainLocksHandler& m_clhandler; @@ -50,10 +52,20 @@ class CSpecialTxProcessor public: explicit CSpecialTxProcessor(CCreditPoolManager& cpoolman, CDeterministicMNManager& dmnman, CMNHFManager& mnhfman, - llmq::CQuorumBlockProcessor& qblockman, const ChainstateManager& chainman, const Consensus::Params& consensus_params, + llmq::CQuorumBlockProcessor& qblockman, llmq::CQuorumSnapshotManager& qsnapman, + const ChainstateManager& chainman, const Consensus::Params& consensus_params, const llmq::CChainLocksHandler& clhandler, const llmq::CQuorumManager& qman) : - m_cpoolman(cpoolman), m_dmnman{dmnman}, m_mnhfman{mnhfman}, m_qblockman{qblockman}, m_chainman(chainman), m_consensus_params{consensus_params}, - m_clhandler{clhandler}, m_qman{qman} {} + m_cpoolman(cpoolman), + m_dmnman{dmnman}, + m_mnhfman{mnhfman}, + m_qblockman{qblockman}, + m_qsnapman{qsnapman}, + m_chainman(chainman), + m_consensus_params{consensus_params}, + m_clhandler{clhandler}, + m_qman{qman} + { + } bool CheckSpecialTx(const CTransaction& tx, const CBlockIndex* pindexPrev, const CCoinsViewCache& view, bool check_sigs, TxValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(cs_main); diff --git a/src/init.cpp b/src/init.cpp index 24bef37c05b47..258be50fee660 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -71,46 +71,37 @@ #include #include #include - #include +#include -#include +#include #include #include -#ifdef ENABLE_WALLET -#include -#include -#endif // ENABLE_WALLET #include #include +#include +#include +#include #include #include +#include +#include +#include +#include #include +#include #include #include #include #include #include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - #include +#ifdef ENABLE_WALLET +#include +#include +#endif // ENABLE_WALLET + #include #include #include @@ -124,8 +115,6 @@ #include #include -#include - #ifndef WIN32 #include #include @@ -335,8 +324,8 @@ void PrepareShutdown(NodeContext& node) chainstate->ResetCoinsViews(); } } - DashChainstateSetupClose(node.chain_helper, node.cpoolman, node.dmnman, node.mnhf_manager, - llmq::quorumSnapshotManager, node.llmq_ctx, Assert(node.mempool.get())); + DashChainstateSetupClose(node.chain_helper, node.cpoolman, node.dmnman, node.mnhf_manager, node.llmq_ctx, + Assert(node.mempool.get())); node.mnhf_manager.reset(); node.evodb.reset(); } @@ -1858,9 +1847,6 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) node.dmnman, node.evodb, node.mnhf_manager, - llmq::chainLocksHandler, - llmq::quorumInstantSendManager, - llmq::quorumSnapshotManager, node.llmq_ctx, Assert(node.mempool.get()), fPruneMode, @@ -2035,7 +2021,8 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) // ********************************************************* Step 7c: Setup CoinJoin node.cj_ctx = std::make_unique(chainman, *node.connman, *node.dmnman, *node.mn_metaman, *node.mempool, - node.mn_activeman.get(), *node.mn_sync, node.peerman, !ignores_incoming_txs); + node.mn_activeman.get(), *node.mn_sync, *node.llmq_ctx->isman, node.peerman, + !ignores_incoming_txs); #ifdef ENABLE_WALLET node.coinjoin_loader = interfaces::MakeCoinJoinLoader(*node.cj_ctx->walletman); diff --git a/src/llmq/blockprocessor.cpp b/src/llmq/blockprocessor.cpp index b11ab32f813ff..bc752d806dee6 100644 --- a/src/llmq/blockprocessor.cpp +++ b/src/llmq/blockprocessor.cpp @@ -26,11 +26,12 @@ #include -static void PreComputeQuorumMembers(CDeterministicMNManager& dmnman, const CBlockIndex* pindex, bool reset_cache = false) +static void PreComputeQuorumMembers(CDeterministicMNManager& dmnman, llmq::CQuorumSnapshotManager& qsnapman, + const CBlockIndex* pindex, bool reset_cache) { for (const Consensus::LLMQParams& params : llmq::GetEnabledQuorumParams(pindex->pprev)) { if (llmq::IsQuorumRotationEnabled(params, pindex) && (pindex->nHeight % params.dkgInterval == 0)) { - llmq::utils::GetAllQuorumMembers(params.type, dmnman, pindex, reset_cache); + llmq::utils::GetAllQuorumMembers(params.type, dmnman, qsnapman, pindex, reset_cache); } } } @@ -43,10 +44,12 @@ static const std::string DB_MINED_COMMITMENT_BY_INVERSED_HEIGHT_Q_INDEXED = "q_m static const std::string DB_BEST_BLOCK_UPGRADE = "q_bbu2"; -CQuorumBlockProcessor::CQuorumBlockProcessor(CChainState& chainstate, CDeterministicMNManager& dmnman, CEvoDB& evoDb) : +CQuorumBlockProcessor::CQuorumBlockProcessor(CChainState& chainstate, CDeterministicMNManager& dmnman, CEvoDB& evoDb, + CQuorumSnapshotManager& qsnapman) : m_chainstate(chainstate), m_dmnman(dmnman), - m_evoDb(evoDb) + m_evoDb(evoDb), + m_qsnapman(qsnapman) { utils::InitQuorumsCache(mapHasMinedCommitmentCache); } @@ -133,7 +136,7 @@ MessageProcessingResult CQuorumBlockProcessor::ProcessMessage(const CNode& peer, } } - if (!qc.Verify(m_dmnman, pQuorumBaseBlockIndex, true)) { + if (!qc.Verify(m_dmnman, m_qsnapman, pQuorumBaseBlockIndex, /*checkSigs=*/true)) { LogPrint(BCLog::LLMQ, "CQuorumBlockProcessor::%s -- commitment for quorum %s:%d is not valid quorumIndex[%d] nversion[%d], peer=%d\n", __func__, qc.quorumHash.ToString(), ToUnderlying(qc.llmqType), qc.quorumIndex, qc.nVersion, peer.GetId()); @@ -159,7 +162,7 @@ bool CQuorumBlockProcessor::ProcessBlock(const CBlock& block, gsl::not_null qcs; if (!GetCommitmentsFromBlock(block, pindex, qcs, state)) { @@ -270,7 +273,7 @@ bool CQuorumBlockProcessor::ProcessCommitment(int nHeight, const uint256& blockH const auto* pQuorumBaseBlockIndex = m_chainstate.m_blockman.LookupBlockIndex(qc.quorumHash); - if (!qc.Verify(m_dmnman, pQuorumBaseBlockIndex, fBLSChecks)) { + if (!qc.Verify(m_dmnman, m_qsnapman, pQuorumBaseBlockIndex, /*checkSigs=*/fBLSChecks)) { LogPrint(BCLog::LLMQ, "CQuorumBlockProcessor::%s height=%d, type=%d, quorumIndex=%d, quorumHash=%s, signers=%s, validMembers=%d, quorumPublicKey=%s qc verify failed.\n", __func__, nHeight, ToUnderlying(qc.llmqType), qc.quorumIndex, quorumHash.ToString(), qc.CountSigners(), qc.CountValidMembers(), qc.quorumPublicKey.ToString()); return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-qc-invalid"); @@ -314,7 +317,7 @@ bool CQuorumBlockProcessor::UndoBlock(const CBlock& block, gsl::not_null qcs; if (BlockValidationState dummy; !GetCommitmentsFromBlock(block, pindex, qcs, dummy)) { diff --git a/src/llmq/blockprocessor.h b/src/llmq/blockprocessor.h index da5dea17fb2d9..b4723674eb5a9 100644 --- a/src/llmq/blockprocessor.h +++ b/src/llmq/blockprocessor.h @@ -30,8 +30,9 @@ extern RecursiveMutex cs_main; namespace llmq { - class CFinalCommitment; +class CQuorumSnapshotManager; + using CFinalCommitmentPtr = std::unique_ptr; class CQuorumBlockProcessor @@ -40,6 +41,7 @@ class CQuorumBlockProcessor CChainState& m_chainstate; CDeterministicMNManager& m_dmnman; CEvoDB& m_evoDb; + CQuorumSnapshotManager& m_qsnapman; mutable Mutex minableCommitmentsCs; std::map, uint256> minableCommitmentsByQuorum GUARDED_BY(minableCommitmentsCs); @@ -48,7 +50,8 @@ class CQuorumBlockProcessor mutable std::map> mapHasMinedCommitmentCache GUARDED_BY(minableCommitmentsCs); public: - explicit CQuorumBlockProcessor(CChainState& chainstate, CDeterministicMNManager& dmnman, CEvoDB& evoDb); + explicit CQuorumBlockProcessor(CChainState& chainstate, CDeterministicMNManager& dmnman, CEvoDB& evoDb, + CQuorumSnapshotManager& qsnapman); MessageProcessingResult ProcessMessage(const CNode& peer, std::string_view msg_type, CDataStream& vRecv); diff --git a/src/llmq/chainlocks.cpp b/src/llmq/chainlocks.cpp index 1b6f56f5c8632..a8abd6f951178 100644 --- a/src/llmq/chainlocks.cpp +++ b/src/llmq/chainlocks.cpp @@ -29,8 +29,6 @@ static bool ChainLocksSigningEnabled(const CSporkManager& sporkman) namespace llmq { -std::unique_ptr chainLocksHandler; - CChainLocksHandler::CChainLocksHandler(CChainState& chainstate, CQuorumManager& _qman, CSigningManager& _sigman, CSigSharesManager& _shareman, CSporkManager& sporkman, CTxMemPool& _mempool, const CMasternodeSync& mn_sync, bool is_masternode) : @@ -54,14 +52,14 @@ CChainLocksHandler::~CChainLocksHandler() scheduler_thread->join(); } -void CChainLocksHandler::Start() +void CChainLocksHandler::Start(const llmq::CInstantSendManager& isman) { sigman.RegisterRecoveredSigsListener(this); scheduler->scheduleEvery([&]() { CheckActiveState(); EnforceBestChainLock(); // regularly retry signing the current chaintip as it might have failed before due to missing islocks - TrySignChainTip(); + TrySignChainTip(isman); }, std::chrono::seconds{5}); } @@ -185,7 +183,7 @@ void CChainLocksHandler::AcceptedBlockHeader(gsl::not_null p } } -void CChainLocksHandler::UpdatedBlockTip() +void CChainLocksHandler::UpdatedBlockTip(const llmq::CInstantSendManager& isman) { // don't call TrySignChainTip directly but instead let the scheduler call it. This way we ensure that cs_main is // never locked and TrySignChainTip is not called twice in parallel. Also avoids recursive calls due to @@ -195,7 +193,7 @@ void CChainLocksHandler::UpdatedBlockTip() scheduler->scheduleFromNow([&]() { CheckActiveState(); EnforceBestChainLock(); - TrySignChainTip(); + TrySignChainTip(isman); tryLockChainTipScheduled = false; }, std::chrono::seconds{0}); } @@ -217,7 +215,7 @@ void CChainLocksHandler::CheckActiveState() } } -void CChainLocksHandler::TrySignChainTip() +void CChainLocksHandler::TrySignChainTip(const llmq::CInstantSendManager& isman) { Cleanup(); @@ -274,7 +272,7 @@ void CChainLocksHandler::TrySignChainTip() // considered safe when it is islocked or at least known since 10 minutes (from mempool or block). These checks are // performed for the tip (which we try to sign) and the previous 5 blocks. If a ChainLocked block is found on the // way down, we consider all TXs to be safe. - if (quorumInstantSendManager->IsInstantSendEnabled() && quorumInstantSendManager->RejectConflictingBlocks()) { + if (isman.IsInstantSendEnabled() && isman.RejectConflictingBlocks()) { const auto* pindexWalk = pindex; while (pindexWalk != nullptr) { if (pindex->nHeight - pindexWalk->nHeight > 5) { @@ -305,7 +303,7 @@ void CChainLocksHandler::TrySignChainTip() } } - if (txAge < WAIT_FOR_ISLOCK_TIMEOUT && !quorumInstantSendManager->IsLocked(txid)) { + if (txAge < WAIT_FOR_ISLOCK_TIMEOUT && !isman.IsLocked(txid)) { LogPrint(BCLog::CHAINLOCKS, "CChainLocksHandler::%s -- not signing block %s due to TX %s not being islocked and not old enough. age=%d\n", __func__, pindexWalk->GetBlockHash().ToString(), txid.ToString(), txAge); return; diff --git a/src/llmq/chainlocks.h b/src/llmq/chainlocks.h index 04c080453b63c..3ceb11b1bf3a2 100644 --- a/src/llmq/chainlocks.h +++ b/src/llmq/chainlocks.h @@ -31,6 +31,7 @@ class CTxMemPool; namespace llmq { +class CInstantSendManager; class CSigningManager; class CSigSharesManager; enum class VerifyRecSigStatus; @@ -89,7 +90,7 @@ class CChainLocksHandler : public CRecoveredSigsListener const CMasternodeSync& mn_sync, bool is_masternode); ~CChainLocksHandler(); - void Start(); + void Start(const llmq::CInstantSendManager& isman); void Stop(); bool AlreadyHave(const CInv& inv) const EXCLUSIVE_LOCKS_REQUIRED(!cs); @@ -100,12 +101,12 @@ class CChainLocksHandler : public CRecoveredSigsListener const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(!cs); void AcceptedBlockHeader(gsl::not_null pindexNew) EXCLUSIVE_LOCKS_REQUIRED(!cs); - void UpdatedBlockTip(); + void UpdatedBlockTip(const llmq::CInstantSendManager& isman); void TransactionAddedToMempool(const CTransactionRef& tx, int64_t nAcceptTime) EXCLUSIVE_LOCKS_REQUIRED(!cs); void BlockConnected(const std::shared_ptr& pblock, gsl::not_null pindex) EXCLUSIVE_LOCKS_REQUIRED(!cs); void BlockDisconnected(const std::shared_ptr& pblock, gsl::not_null pindexDisconnected) EXCLUSIVE_LOCKS_REQUIRED(!cs); void CheckActiveState() EXCLUSIVE_LOCKS_REQUIRED(!cs); - void TrySignChainTip() EXCLUSIVE_LOCKS_REQUIRED(!cs); + void TrySignChainTip(const llmq::CInstantSendManager& isman) EXCLUSIVE_LOCKS_REQUIRED(!cs); void EnforceBestChainLock() EXCLUSIVE_LOCKS_REQUIRED(!cs); [[nodiscard]] MessageProcessingResult HandleNewRecoveredSig(const CRecoveredSig& recoveredSig) override EXCLUSIVE_LOCKS_REQUIRED(!cs); @@ -126,8 +127,6 @@ class CChainLocksHandler : public CRecoveredSigsListener void Cleanup() EXCLUSIVE_LOCKS_REQUIRED(!cs); }; -extern std::unique_ptr chainLocksHandler; - bool AreChainLocksEnabled(const CSporkManager& sporkman); } // namespace llmq diff --git a/src/llmq/commitment.cpp b/src/llmq/commitment.cpp index 607be69f1b63a..4727fa2533f4e 100644 --- a/src/llmq/commitment.cpp +++ b/src/llmq/commitment.cpp @@ -27,7 +27,8 @@ CFinalCommitment::CFinalCommitment(const Consensus::LLMQParams& params, const ui { } -bool CFinalCommitment::Verify(CDeterministicMNManager& dmnman, gsl::not_null pQuorumBaseBlockIndex, bool checkSigs) const +bool CFinalCommitment::Verify(CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, + gsl::not_null pQuorumBaseBlockIndex, bool checkSigs) const { const auto& llmq_params_opt = Params().GetLLMQ(llmqType); if (!llmq_params_opt.has_value()) { @@ -81,7 +82,7 @@ bool CFinalCommitment::Verify(CDeterministicMNManager& dmnman, gsl::not_null pindexPrev, TxValidationState& state) +bool CheckLLMQCommitment(CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, + const ChainstateManager& chainman, const CTransaction& tx, + gsl::not_null pindexPrev, TxValidationState& state) { const auto opt_qcTx = GetTxPayload(tx); if (!opt_qcTx) { @@ -219,7 +222,7 @@ bool CheckLLMQCommitment(CDeterministicMNManager& dmnman, const ChainstateManage return true; } - if (!qcTx.commitment.Verify(dmnman, pQuorumBaseBlockIndex, false)) { + if (!qcTx.commitment.Verify(dmnman, qsnapman, pQuorumBaseBlockIndex, false)) { LogPrint(BCLog::LLMQ, "CFinalCommitment -- h[%d] invalid qcTx.commitment[%s] Verify failed\n", pindexPrev->nHeight, qcTx.commitment.quorumHash.ToString()); return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-qc-invalid"); } diff --git a/src/llmq/commitment.h b/src/llmq/commitment.h index 3cb02b93b50df..6adbdcbb4c7fc 100644 --- a/src/llmq/commitment.h +++ b/src/llmq/commitment.h @@ -27,6 +27,7 @@ class TxValidationState; namespace llmq { +class CQuorumSnapshotManager; // This message is an aggregation of all received premature commitments and only valid if // enough (>=threshold) premature commitments were aggregated @@ -65,7 +66,8 @@ class CFinalCommitment return int(std::count(validMembers.begin(), validMembers.end(), true)); } - bool Verify(CDeterministicMNManager& dmnman, gsl::not_null pQuorumBaseBlockIndex, bool checkSigs) const; + bool Verify(CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, + gsl::not_null pQuorumBaseBlockIndex, bool checkSigs) const; bool VerifyNull() const; bool VerifySizes(const Consensus::LLMQParams& params) const; @@ -175,7 +177,9 @@ class CFinalCommitmentTxPayload } }; -bool CheckLLMQCommitment(CDeterministicMNManager& dmnman, const ChainstateManager& chainman, const CTransaction& tx, gsl::not_null pindexPrev, TxValidationState& state); +bool CheckLLMQCommitment(CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, + const ChainstateManager& chainman, const CTransaction& tx, + gsl::not_null pindexPrev, TxValidationState& state); uint256 BuildCommitmentHash(Consensus::LLMQType llmqType, const uint256& blockHash, const std::vector& validMembers, const CBLSPublicKey& pubKey, const uint256& vvecHash); diff --git a/src/llmq/context.cpp b/src/llmq/context.cpp index 8e8307b5c5075..876c38334f177 100644 --- a/src/llmq/context.cpp +++ b/src/llmq/context.cpp @@ -17,6 +17,7 @@ #include #include #include +#include LLMQContext::LLMQContext(ChainstateManager& chainman, CDeterministicMNManager& dmnman, CEvoDB& evo_db, CMasternodeMetaMan& mn_metaman, CMNHFManager& mnhfman, CSporkManager& sporkman, @@ -25,31 +26,21 @@ LLMQContext::LLMQContext(ChainstateManager& chainman, CDeterministicMNManager& d is_masternode{mn_activeman != nullptr}, bls_worker{std::make_shared()}, dkg_debugman{std::make_unique()}, - quorum_block_processor{std::make_unique(chainman.ActiveChainstate(), dmnman, evo_db)}, + qsnapman{std::make_unique(evo_db)}, + quorum_block_processor{ + std::make_unique(chainman.ActiveChainstate(), dmnman, evo_db, *qsnapman)}, qdkgsman{std::make_unique(*bls_worker, chainman.ActiveChainstate(), dmnman, *dkg_debugman, - mn_metaman, *quorum_block_processor, mn_activeman, sporkman, - unit_tests, wipe)}, + mn_metaman, *quorum_block_processor, *qsnapman, mn_activeman, + sporkman, unit_tests, wipe)}, qman{std::make_unique(*bls_worker, chainman.ActiveChainstate(), dmnman, *qdkgsman, evo_db, - *quorum_block_processor, mn_activeman, mn_sync, sporkman, unit_tests, - wipe)}, + *quorum_block_processor, *qsnapman, mn_activeman, mn_sync, sporkman, + unit_tests, wipe)}, sigman{std::make_unique(mn_activeman, chainman.ActiveChainstate(), *qman, unit_tests, wipe)}, shareman{std::make_unique(*sigman, mn_activeman, *qman, sporkman)}, - clhandler{[&]() -> llmq::CChainLocksHandler* const { - assert(llmq::chainLocksHandler == nullptr); - llmq::chainLocksHandler = std::make_unique(chainman.ActiveChainstate(), *qman, - *sigman, *shareman, sporkman, mempool, - mn_sync, is_masternode); - return llmq::chainLocksHandler.get(); - }()}, - isman{[&]() -> llmq::CInstantSendManager* const { - assert(llmq::quorumInstantSendManager == nullptr); - llmq::quorumInstantSendManager = std::make_unique(*llmq::chainLocksHandler, - chainman.ActiveChainstate(), *qman, - *sigman, *shareman, sporkman, - mempool, mn_sync, is_masternode, - unit_tests, wipe); - return llmq::quorumInstantSendManager.get(); - }()}, + clhandler{std::make_unique(chainman.ActiveChainstate(), *qman, *sigman, *shareman, + sporkman, mempool, mn_sync, is_masternode)}, + isman{std::make_unique(*clhandler, chainman.ActiveChainstate(), *qman, *sigman, *shareman, + sporkman, mempool, mn_sync, is_masternode, unit_tests, wipe)}, ehfSignalsHandler{std::make_unique(chainman, mnhfman, *sigman, *shareman, *qman)} { // Have to start it early to let VerifyDB check ChainLock signatures in coinbase @@ -58,44 +49,30 @@ LLMQContext::LLMQContext(ChainstateManager& chainman, CDeterministicMNManager& d LLMQContext::~LLMQContext() { bls_worker->Stop(); - - // LLMQContext doesn't own these objects, but still need to care of them for consistency: - llmq::quorumInstantSendManager.reset(); - llmq::chainLocksHandler.reset(); } void LLMQContext::Interrupt() { - sigman->InterruptWorkerThread(); + isman->InterruptWorkerThread(); shareman->InterruptWorkerThread(); - - assert(isman == llmq::quorumInstantSendManager.get()); - llmq::quorumInstantSendManager->InterruptWorkerThread(); + sigman->InterruptWorkerThread(); } void LLMQContext::Start(CConnman& connman, PeerManager& peerman) { - assert(clhandler == llmq::chainLocksHandler.get()); - assert(isman == llmq::quorumInstantSendManager.get()); - if (is_masternode) { qdkgsman->StartThreads(connman, peerman); } qman->Start(); + sigman->StartWorkerThread(peerman); shareman->RegisterAsRecoveredSigsListener(); shareman->StartWorkerThread(connman, peerman); - sigman->StartWorkerThread(peerman); - - llmq::chainLocksHandler->Start(); - llmq::quorumInstantSendManager->Start(peerman); + clhandler->Start(*isman); + isman->Start(peerman); } void LLMQContext::Stop() { - assert(clhandler == llmq::chainLocksHandler.get()); - assert(isman == llmq::quorumInstantSendManager.get()); - - llmq::quorumInstantSendManager->Stop(); - llmq::chainLocksHandler->Stop(); - + isman->Stop(); + clhandler->Stop(); shareman->StopWorkerThread(); shareman->UnregisterAsRecoveredSigsListener(); sigman->StopWorkerThread(); diff --git a/src/llmq/context.h b/src/llmq/context.h index 0e92e6a90fce6..deb395dce3fdc 100644 --- a/src/llmq/context.h +++ b/src/llmq/context.h @@ -28,6 +28,7 @@ class CEHFSignalsHandler; class CInstantSendManager; class CQuorumBlockProcessor; class CQuorumManager; +class CQuorumSnapshotManager; class CSigSharesManager; class CSigningManager; } @@ -61,13 +62,14 @@ struct LLMQContext { */ const std::shared_ptr bls_worker; const std::unique_ptr dkg_debugman; + const std::unique_ptr qsnapman; const std::unique_ptr quorum_block_processor; const std::unique_ptr qdkgsman; const std::unique_ptr qman; const std::unique_ptr sigman; const std::unique_ptr shareman; - llmq::CChainLocksHandler* const clhandler; - llmq::CInstantSendManager* const isman; + const std::unique_ptr clhandler; + const std::unique_ptr isman; // TODO: split CInstantSendManager and CInstantSendLock to 2 files const std::unique_ptr ehfSignalsHandler; }; diff --git a/src/llmq/debug.cpp b/src/llmq/debug.cpp index c042fd0c98602..9e70b3bff319e 100644 --- a/src/llmq/debug.cpp +++ b/src/llmq/debug.cpp @@ -15,8 +15,8 @@ namespace llmq { -UniValue CDKGDebugSessionStatus::ToJson(CDeterministicMNManager& dmnman, const ChainstateManager& chainman, - int quorumIndex, int detailLevel) const +UniValue CDKGDebugSessionStatus::ToJson(CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, + const ChainstateManager& chainman, int quorumIndex, int detailLevel) const { UniValue ret(UniValue::VOBJ); @@ -28,7 +28,7 @@ UniValue CDKGDebugSessionStatus::ToJson(CDeterministicMNManager& dmnman, const C if (detailLevel == 2) { const CBlockIndex* pindex = WITH_LOCK(cs_main, return chainman.m_blockman.LookupBlockIndex(quorumHash)); if (pindex != nullptr) { - dmnMembers = utils::GetAllQuorumMembers(llmqType, dmnman, pindex); + dmnMembers = utils::GetAllQuorumMembers(llmqType, dmnman, qsnapman, pindex); } } @@ -109,8 +109,8 @@ UniValue CDKGDebugSessionStatus::ToJson(CDeterministicMNManager& dmnman, const C CDKGDebugManager::CDKGDebugManager() = default; -UniValue CDKGDebugStatus::ToJson(CDeterministicMNManager& dmnman, const ChainstateManager& chainman, - int detailLevel) const +UniValue CDKGDebugStatus::ToJson(CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, + const ChainstateManager& chainman, int detailLevel) const { UniValue ret(UniValue::VOBJ); @@ -127,7 +127,7 @@ UniValue CDKGDebugStatus::ToJson(CDeterministicMNManager& dmnman, const Chainsta UniValue s(UniValue::VOBJ); s.pushKV("llmqType", std::string(llmq_params_opt->name)); s.pushKV("quorumIndex", p.first.second); - s.pushKV("status", p.second.ToJson(dmnman, chainman, p.first.second, detailLevel)); + s.pushKV("status", p.second.ToJson(dmnman, qsnapman, chainman, p.first.second, detailLevel)); sessionsArrJson.push_back(s); } diff --git a/src/llmq/debug.h b/src/llmq/debug.h index 7498a281ab6d3..337ce82de1a90 100644 --- a/src/llmq/debug.h +++ b/src/llmq/debug.h @@ -20,6 +20,7 @@ class CScheduler; namespace llmq { +class CQuorumSnapshotManager; enum class QuorumPhase; @@ -76,8 +77,8 @@ class CDKGDebugSessionStatus public: CDKGDebugSessionStatus() : statusBitset(0) {} - UniValue ToJson(CDeterministicMNManager& dmnman, const ChainstateManager& chainman, - int quorumIndex, int detailLevel) const; + UniValue ToJson(CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, + const ChainstateManager& chainman, int quorumIndex, int detailLevel) const; }; class CDKGDebugStatus @@ -89,8 +90,8 @@ class CDKGDebugStatus //std::map sessions; public: - UniValue ToJson(CDeterministicMNManager& dmnman, const ChainstateManager& chainman, - int detailLevel) const; + UniValue ToJson(CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, + const ChainstateManager& chainman, int detailLevel) const; }; class CDKGDebugManager diff --git a/src/llmq/dkgsession.cpp b/src/llmq/dkgsession.cpp index b63ebf45a4e0f..2423b71f85de0 100644 --- a/src/llmq/dkgsession.cpp +++ b/src/llmq/dkgsession.cpp @@ -74,7 +74,8 @@ CDKGMember::CDKGMember(const CDeterministicMNCPtr& _dmn, size_t _idx) : CDKGSession::CDKGSession(const CBlockIndex* pQuorumBaseBlockIndex, const Consensus::LLMQParams& _params, CBLSWorker& _blsWorker, CDeterministicMNManager& dmnman, CDKGSessionManager& _dkgManager, CDKGDebugManager& _dkgDebugManager, CMasternodeMetaMan& mn_metaman, - const CActiveMasternodeManager* const mn_activeman, const CSporkManager& sporkman) : + CQuorumSnapshotManager& qsnapman, const CActiveMasternodeManager* const mn_activeman, + const CSporkManager& sporkman) : params(_params), blsWorker(_blsWorker), cache(_blsWorker), @@ -82,6 +83,7 @@ CDKGSession::CDKGSession(const CBlockIndex* pQuorumBaseBlockIndex, const Consens dkgManager(_dkgManager), dkgDebugManager(_dkgDebugManager), m_mn_metaman(mn_metaman), + m_qsnapman(qsnapman), m_mn_activeman(mn_activeman), m_sporkman(sporkman), m_quorum_base_block_index{pQuorumBaseBlockIndex} @@ -90,7 +92,7 @@ CDKGSession::CDKGSession(const CBlockIndex* pQuorumBaseBlockIndex, const Consens bool CDKGSession::Init(const uint256& _myProTxHash, int _quorumIndex) { - const auto mns = utils::GetAllQuorumMembers(params.type, m_dmnman, m_quorum_base_block_index); + const auto mns = utils::GetAllQuorumMembers(params.type, m_dmnman, m_qsnapman, m_quorum_base_block_index); quorumIndex = _quorumIndex; members.resize(mns.size()); memberIds.resize(members.size()); @@ -135,7 +137,8 @@ bool CDKGSession::Init(const uint256& _myProTxHash, int _quorumIndex) if (!myProTxHash.IsNull()) { dkgDebugManager.InitLocalSessionStatus(params, quorumIndex, m_quorum_base_block_index->GetBlockHash(), m_quorum_base_block_index->nHeight); - relayMembers = utils::GetQuorumRelayMembers(params, m_dmnman, m_quorum_base_block_index, myProTxHash, true); + relayMembers = utils::GetQuorumRelayMembers(params, m_dmnman, m_qsnapman, m_quorum_base_block_index, + myProTxHash, true); if (LogAcceptDebug(BCLog::LLMQ)) { std::stringstream ss; for (const auto& r : relayMembers) { @@ -1272,7 +1275,7 @@ std::vector CDKGSession::FinalizeCommitments() t2.stop(); cxxtimer::Timer t3(true); - if (!fqc.Verify(m_dmnman, m_quorum_base_block_index, true)) { + if (!fqc.Verify(m_dmnman, m_qsnapman, m_quorum_base_block_index, true)) { logger.Batch("failed to verify final commitment"); continue; } diff --git a/src/llmq/dkgsession.h b/src/llmq/dkgsession.h index b1897482fcee9..6e8a4170a7556 100644 --- a/src/llmq/dkgsession.h +++ b/src/llmq/dkgsession.h @@ -36,6 +36,7 @@ class CDKGDebugManager; class CDKGSession; class CDKGSessionManager; class CDKGPendingMessages; +class CQuorumSnapshotManager; class CDKGContribution { @@ -286,6 +287,7 @@ class CDKGSession CDKGSessionManager& dkgManager; CDKGDebugManager& dkgDebugManager; CMasternodeMetaMan& m_mn_metaman; + CQuorumSnapshotManager& m_qsnapman; const CActiveMasternodeManager* const m_mn_activeman; const CSporkManager& m_sporkman; @@ -329,8 +331,8 @@ class CDKGSession public: CDKGSession(const CBlockIndex* pQuorumBaseBlockIndex, const Consensus::LLMQParams& _params, CBLSWorker& _blsWorker, CDeterministicMNManager& dmnman, CDKGSessionManager& _dkgManager, CDKGDebugManager& _dkgDebugManager, - CMasternodeMetaMan& mn_metaman, const CActiveMasternodeManager* const mn_activeman, - const CSporkManager& sporkman); + CMasternodeMetaMan& mn_metaman, CQuorumSnapshotManager& qsnapman, + const CActiveMasternodeManager* const mn_activeman, const CSporkManager& sporkman); // TODO: remove Init completely bool Init(const uint256& _myProTxHash, int _quorumIndex); diff --git a/src/llmq/dkgsessionhandler.cpp b/src/llmq/dkgsessionhandler.cpp index 107bbf98af967..95b1c0fd3372d 100644 --- a/src/llmq/dkgsessionhandler.cpp +++ b/src/llmq/dkgsessionhandler.cpp @@ -27,6 +27,7 @@ namespace llmq CDKGSessionHandler::CDKGSessionHandler(CBLSWorker& _blsWorker, CChainState& chainstate, CDeterministicMNManager& dmnman, CDKGDebugManager& _dkgDebugManager, CDKGSessionManager& _dkgManager, CMasternodeMetaMan& mn_metaman, CQuorumBlockProcessor& _quorumBlockProcessor, + CQuorumSnapshotManager& qsnapman, const CActiveMasternodeManager* const mn_activeman, const CSporkManager& sporkman, const Consensus::LLMQParams& _params, int _quorumIndex) : blsWorker(_blsWorker), @@ -36,12 +37,13 @@ CDKGSessionHandler::CDKGSessionHandler(CBLSWorker& _blsWorker, CChainState& chai dkgManager(_dkgManager), m_mn_metaman(mn_metaman), quorumBlockProcessor(_quorumBlockProcessor), + m_qsnapman(qsnapman), m_mn_activeman(mn_activeman), m_sporkman(sporkman), params(_params), quorumIndex(_quorumIndex), curSession(std::make_unique(nullptr, _params, _blsWorker, dmnman, _dkgManager, _dkgDebugManager, - m_mn_metaman, m_mn_activeman, sporkman)), + m_mn_metaman, m_qsnapman, m_mn_activeman, sporkman)), pendingContributions( (size_t)_params.size * 2, MSG_QUORUM_CONTRIB), // we allow size*2 messages as we need to make sure we see bad behavior (double messages) @@ -189,7 +191,7 @@ bool CDKGSessionHandler::InitNewQuorum(const CBlockIndex* pQuorumBaseBlockIndex) } curSession = std::make_unique(pQuorumBaseBlockIndex, params, blsWorker, m_dmnman, dkgManager, - dkgDebugManager, m_mn_metaman, m_mn_activeman, m_sporkman); + dkgDebugManager, m_mn_metaman, m_qsnapman, m_mn_activeman, m_sporkman); if (!curSession->Init(m_mn_activeman->GetProTxHash(), quorumIndex)) { LogPrintf("CDKGSessionManager::%s -- height[%d] quorum initialization failed for %s qi[%d]\n", __func__, @@ -548,9 +550,11 @@ void CDKGSessionHandler::HandleDKGRound(CConnman& connman, PeerManager& peerman) }); const auto tip_mn_list = m_dmnman.GetListAtChainTip(); - utils::EnsureQuorumConnections(params, connman, m_dmnman, m_sporkman, tip_mn_list, pQuorumBaseBlockIndex, curSession->myProTxHash, /* is_masternode = */ m_mn_activeman != nullptr); + utils::EnsureQuorumConnections(params, connman, m_dmnman, m_sporkman, m_qsnapman, tip_mn_list, pQuorumBaseBlockIndex, + curSession->myProTxHash, /* is_masternode = */ m_mn_activeman != nullptr); if (curSession->AreWeMember()) { - utils::AddQuorumProbeConnections(params, connman, m_dmnman, m_mn_metaman, m_sporkman, tip_mn_list, pQuorumBaseBlockIndex, curSession->myProTxHash); + utils::AddQuorumProbeConnections(params, connman, m_dmnman, m_mn_metaman, m_qsnapman, m_sporkman, tip_mn_list, + pQuorumBaseBlockIndex, curSession->myProTxHash); } WaitForNextPhase(QuorumPhase::Initialized, QuorumPhase::Contribute, curQuorumHash); diff --git a/src/llmq/dkgsessionhandler.h b/src/llmq/dkgsessionhandler.h index b28ae87e44a14..6f320894a58ef 100644 --- a/src/llmq/dkgsessionhandler.h +++ b/src/llmq/dkgsessionhandler.h @@ -38,6 +38,7 @@ class CDKGDebugManager; class CDKGSession; class CDKGSessionManager; class CQuorumBlockProcessor; +class CQuorumSnapshotManager; enum class QuorumPhase { Initialized = 1, @@ -134,6 +135,7 @@ class CDKGSessionHandler CDKGSessionManager& dkgManager; CMasternodeMetaMan& m_mn_metaman; CQuorumBlockProcessor& quorumBlockProcessor; + CQuorumSnapshotManager& m_qsnapman; const CActiveMasternodeManager* const m_mn_activeman; const CSporkManager& m_sporkman; const Consensus::LLMQParams params; @@ -156,8 +158,9 @@ class CDKGSessionHandler public: CDKGSessionHandler(CBLSWorker& _blsWorker, CChainState& chainstate, CDeterministicMNManager& dmnman, - CDKGDebugManager& _dkgDebugManager, CDKGSessionManager& _dkgManager, CMasternodeMetaMan& mn_metaman, - CQuorumBlockProcessor& _quorumBlockProcessor, const CActiveMasternodeManager* const mn_activeman, + CDKGDebugManager& _dkgDebugManager, CDKGSessionManager& _dkgManager, + CMasternodeMetaMan& mn_metaman, CQuorumBlockProcessor& _quorumBlockProcessor, + CQuorumSnapshotManager& qsnapman, const CActiveMasternodeManager* const mn_activeman, const CSporkManager& sporkman, const Consensus::LLMQParams& _params, int _quorumIndex); ~CDKGSessionHandler(); diff --git a/src/llmq/dkgsessionmgr.cpp b/src/llmq/dkgsessionmgr.cpp index d6fb0715c1014..12481b0120e38 100644 --- a/src/llmq/dkgsessionmgr.cpp +++ b/src/llmq/dkgsessionmgr.cpp @@ -31,7 +31,7 @@ static const std::string DB_ENC_CONTRIB = "qdkg_E"; CDKGSessionManager::CDKGSessionManager(CBLSWorker& _blsWorker, CChainState& chainstate, CDeterministicMNManager& dmnman, CDKGDebugManager& _dkgDebugManager, CMasternodeMetaMan& mn_metaman, - CQuorumBlockProcessor& _quorumBlockProcessor, + CQuorumBlockProcessor& _quorumBlockProcessor, CQuorumSnapshotManager& qsnapman, const CActiveMasternodeManager* const mn_activeman, const CSporkManager& sporkman, bool unitTests, bool fWipe) : db(std::make_unique(unitTests ? "" : (gArgs.GetDataDirNet() / "llmq/dkgdb"), 1 << 20, unitTests, fWipe)), @@ -40,6 +40,7 @@ CDKGSessionManager::CDKGSessionManager(CBLSWorker& _blsWorker, CChainState& chai m_dmnman(dmnman), dkgDebugManager(_dkgDebugManager), quorumBlockProcessor(_quorumBlockProcessor), + m_qsnapman(qsnapman), spork_manager(sporkman) { if (mn_activeman == nullptr && !IsWatchQuorumsEnabled()) { @@ -53,7 +54,7 @@ CDKGSessionManager::CDKGSessionManager(CBLSWorker& _blsWorker, CChainState& chai for (const auto i : irange::range(session_count)) { dkgSessionHandlers.emplace(std::piecewise_construct, std::forward_as_tuple(params.type, i), std::forward_as_tuple(blsWorker, m_chainstate, dmnman, dkgDebugManager, *this, - mn_metaman, quorumBlockProcessor, mn_activeman, + mn_metaman, quorumBlockProcessor, m_qsnapman, mn_activeman, spork_manager, params, i)); } } @@ -297,7 +298,7 @@ void CDKGSessionManager::WriteEncryptedContributions(Consensus::LLMQType llmqTyp bool CDKGSessionManager::GetVerifiedContributions(Consensus::LLMQType llmqType, const CBlockIndex* pQuorumBaseBlockIndex, const std::vector& validMembers, std::vector& memberIndexesRet, std::vector& vvecsRet, std::vector& skContributionsRet) const { - auto members = utils::GetAllQuorumMembers(llmqType, m_dmnman, pQuorumBaseBlockIndex); + auto members = utils::GetAllQuorumMembers(llmqType, m_dmnman, m_qsnapman, pQuorumBaseBlockIndex); memberIndexesRet.clear(); vvecsRet.clear(); @@ -343,7 +344,7 @@ bool CDKGSessionManager::GetVerifiedContributions(Consensus::LLMQType llmqType, bool CDKGSessionManager::GetEncryptedContributions(Consensus::LLMQType llmqType, const CBlockIndex* pQuorumBaseBlockIndex, const std::vector& validMembers, const uint256& nProTxHash, std::vector>& vecRet) const { - auto members = utils::GetAllQuorumMembers(llmqType, m_dmnman, pQuorumBaseBlockIndex); + auto members = utils::GetAllQuorumMembers(llmqType, m_dmnman, m_qsnapman, pQuorumBaseBlockIndex); vecRet.clear(); vecRet.reserve(members.size()); diff --git a/src/llmq/dkgsessionmgr.h b/src/llmq/dkgsessionmgr.h index eaa5dc79deae3..2b84c35fa5b94 100644 --- a/src/llmq/dkgsessionmgr.h +++ b/src/llmq/dkgsessionmgr.h @@ -32,6 +32,7 @@ class UniValue; namespace llmq { +class CQuorumSnapshotManager; class CDKGSessionManager { @@ -45,6 +46,7 @@ class CDKGSessionManager CDeterministicMNManager& m_dmnman; CDKGDebugManager& dkgDebugManager; CQuorumBlockProcessor& quorumBlockProcessor; + CQuorumSnapshotManager& m_qsnapman; const CSporkManager& spork_manager; //TODO name struct instead of std::pair @@ -72,8 +74,9 @@ class CDKGSessionManager public: CDKGSessionManager(CBLSWorker& _blsWorker, CChainState& chainstate, CDeterministicMNManager& dmnman, CDKGDebugManager& _dkgDebugManager, CMasternodeMetaMan& mn_metaman, - CQuorumBlockProcessor& _quorumBlockProcessor, const CActiveMasternodeManager* const mn_activeman, - const CSporkManager& sporkman, bool unitTests, bool fWipe); + CQuorumBlockProcessor& _quorumBlockProcessor, CQuorumSnapshotManager& qsnapman, + const CActiveMasternodeManager* const mn_activeman, const CSporkManager& sporkman, + bool unitTests, bool fWipe); ~CDKGSessionManager(); void StartThreads(CConnman& connman, PeerManager& peerman); diff --git a/src/llmq/instantsend.cpp b/src/llmq/instantsend.cpp index f5d9a9299b519..7e4e8c40567d7 100644 --- a/src/llmq/instantsend.cpp +++ b/src/llmq/instantsend.cpp @@ -41,8 +41,6 @@ static const std::string_view DB_ARCHIVED_BY_HASH = "is_a2"; static const std::string_view DB_VERSION = "is_v"; -std::unique_ptr quorumInstantSendManager; - uint256 CInstantSendLock::GetRequestId() const { CHashWriter hw(SER_GETHASH, 0); diff --git a/src/llmq/instantsend.h b/src/llmq/instantsend.h index 158ce1b699c98..6ccc8eaaa6ba0 100644 --- a/src/llmq/instantsend.h +++ b/src/llmq/instantsend.h @@ -365,9 +365,6 @@ class CInstantSendManager : public CRecoveredSigsListener bool IsInstantSendMempoolSigningEnabled() const; bool RejectConflictingBlocks() const; }; -// TODO: split CInstantSendManager and CInstantSendLock to 2 files -extern std::unique_ptr quorumInstantSendManager; - } // namespace llmq #endif // BITCOIN_LLMQ_INSTANTSEND_H diff --git a/src/llmq/quorums.cpp b/src/llmq/quorums.cpp index a27fa044943c2..212aeb685735d 100644 --- a/src/llmq/quorums.cpp +++ b/src/llmq/quorums.cpp @@ -212,7 +212,7 @@ bool CQuorum::ReadContributions(const CDBWrapper& db) CQuorumManager::CQuorumManager(CBLSWorker& _blsWorker, CChainState& chainstate, CDeterministicMNManager& dmnman, CDKGSessionManager& _dkgManager, CEvoDB& _evoDb, - CQuorumBlockProcessor& _quorumBlockProcessor, + CQuorumBlockProcessor& _quorumBlockProcessor, CQuorumSnapshotManager& qsnapman, const CActiveMasternodeManager* const mn_activeman, const CMasternodeSync& mn_sync, const CSporkManager& sporkman, bool unit_tests, bool wipe) : db(std::make_unique(unit_tests ? "" : (gArgs.GetDataDirNet() / "llmq" / "quorumdb"), 1 << 20, @@ -222,6 +222,7 @@ CQuorumManager::CQuorumManager(CBLSWorker& _blsWorker, CChainState& chainstate, m_dmnman(dmnman), dkgManager(_dkgManager), quorumBlockProcessor(_quorumBlockProcessor), + m_qsnapman(qsnapman), m_mn_activeman(mn_activeman), m_mn_sync(mn_sync), m_sporkman(sporkman) @@ -365,7 +366,9 @@ void CQuorumManager::CheckQuorumConnections(CConnman& connman, const Consensus:: }); for (const auto& quorum : lastQuorums) { - if (utils::EnsureQuorumConnections(llmqParams, connman, m_dmnman, m_sporkman, m_dmnman.GetListAtChainTip(), quorum->m_quorum_base_block_index, myProTxHash, /* is_masternode = */ m_mn_activeman != nullptr)) { + if (utils::EnsureQuorumConnections(llmqParams, connman, m_dmnman, m_sporkman, m_qsnapman, + m_dmnman.GetListAtChainTip(), quorum->m_quorum_base_block_index, myProTxHash, + /* is_masternode = */ m_mn_activeman != nullptr)) { if (connmanQuorumsToDelete.erase(quorum->qc->quorumHash) > 0) { LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- llmqType[%d] h[%d] keeping mn quorum connections for quorum: [%d:%s]\n", __func__, ToUnderlying(llmqParams.type), pindexNew->nHeight, quorum->m_quorum_base_block_index->nHeight, quorum->m_quorum_base_block_index->GetBlockHash().ToString()); } @@ -407,7 +410,7 @@ CQuorumPtr CQuorumManager::BuildQuorumFromCommitment(const Consensus::LLMQType l const auto& llmq_params_opt = Params().GetLLMQ(llmqType); assert(llmq_params_opt.has_value()); auto quorum = std::make_shared(llmq_params_opt.value(), blsWorker); - auto members = utils::GetAllQuorumMembers(qc->llmqType, m_dmnman, pQuorumBaseBlockIndex); + auto members = utils::GetAllQuorumMembers(qc->llmqType, m_dmnman, m_qsnapman, pQuorumBaseBlockIndex); quorum->Init(std::move(qc), pQuorumBaseBlockIndex, minedBlockHash, members); diff --git a/src/llmq/quorums.h b/src/llmq/quorums.h index 645802efa6ce9..56924940ce3af 100644 --- a/src/llmq/quorums.h +++ b/src/llmq/quorums.h @@ -48,6 +48,7 @@ enum class VerifyRecSigStatus class CDKGSessionManager; class CQuorumBlockProcessor; +class CQuorumSnapshotManager; /** * Object used as a key to store CQuorumDataRequest @@ -241,6 +242,7 @@ class CQuorumManager CDeterministicMNManager& m_dmnman; CDKGSessionManager& dkgManager; CQuorumBlockProcessor& quorumBlockProcessor; + CQuorumSnapshotManager& m_qsnapman; const CActiveMasternodeManager* const m_mn_activeman; const CMasternodeSync& m_mn_sync; const CSporkManager& m_sporkman; @@ -262,8 +264,8 @@ class CQuorumManager public: CQuorumManager(CBLSWorker& _blsWorker, CChainState& chainstate, CDeterministicMNManager& dmnman, CDKGSessionManager& _dkgManager, CEvoDB& _evoDb, CQuorumBlockProcessor& _quorumBlockProcessor, - const CActiveMasternodeManager* const mn_activeman, const CMasternodeSync& mn_sync, - const CSporkManager& sporkman, bool unit_tests, bool wipe); + CQuorumSnapshotManager& qsnapman, const CActiveMasternodeManager* const mn_activeman, + const CMasternodeSync& mn_sync, const CSporkManager& sporkman, bool unit_tests, bool wipe); ~CQuorumManager(); void Start(); diff --git a/src/llmq/snapshot.cpp b/src/llmq/snapshot.cpp index 7b349fb31db57..932139f8442b3 100644 --- a/src/llmq/snapshot.cpp +++ b/src/llmq/snapshot.cpp @@ -21,8 +21,6 @@ namespace llmq { static const std::string DB_QUORUM_SNAPSHOT = "llmq_S"; -std::unique_ptr quorumSnapshotManager; - UniValue CQuorumSnapshot::ToJson() const { UniValue obj; @@ -86,7 +84,8 @@ UniValue CQuorumRotationInfo::ToJson() const return obj; } -bool BuildQuorumRotationInfo(CDeterministicMNManager& dmnman, const ChainstateManager& chainman, const CQuorumManager& qman, +bool BuildQuorumRotationInfo(CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, + const ChainstateManager& chainman, const CQuorumManager& qman, const CQuorumBlockProcessor& qblockman, const CGetQuorumRotationInfo& request, CQuorumRotationInfo& response, std::string& errorRet) { @@ -207,7 +206,7 @@ bool BuildQuorumRotationInfo(CDeterministicMNManager& dmnman, const ChainstateMa return false; } - auto snapshotHMinusC = quorumSnapshotManager->GetSnapshotForBlock(llmqType, pBlockHMinusCIndex); + auto snapshotHMinusC = qsnapman.GetSnapshotForBlock(llmqType, pBlockHMinusCIndex); if (!snapshotHMinusC.has_value()) { errorRet = strprintf("Can not find quorum snapshot at H-C"); return false; @@ -219,7 +218,7 @@ bool BuildQuorumRotationInfo(CDeterministicMNManager& dmnman, const ChainstateMa return false; } - auto snapshotHMinus2C = quorumSnapshotManager->GetSnapshotForBlock(llmqType, pBlockHMinus2CIndex); + auto snapshotHMinus2C = qsnapman.GetSnapshotForBlock(llmqType, pBlockHMinus2CIndex); if (!snapshotHMinus2C.has_value()) { errorRet = strprintf("Can not find quorum snapshot at H-2C"); return false; @@ -231,7 +230,7 @@ bool BuildQuorumRotationInfo(CDeterministicMNManager& dmnman, const ChainstateMa return false; } - auto snapshotHMinus3C = quorumSnapshotManager->GetSnapshotForBlock(llmqType, pBlockHMinus3CIndex); + auto snapshotHMinus3C = qsnapman.GetSnapshotForBlock(llmqType, pBlockHMinus3CIndex); if (!snapshotHMinus3C.has_value()) { errorRet = strprintf("Can not find quorum snapshot at H-3C"); return false; @@ -247,7 +246,7 @@ bool BuildQuorumRotationInfo(CDeterministicMNManager& dmnman, const ChainstateMa return false; } - auto snapshotHMinus4C = quorumSnapshotManager->GetSnapshotForBlock(llmqType, pBlockHMinus4CIndex); + auto snapshotHMinus4C = qsnapman.GetSnapshotForBlock(llmqType, pBlockHMinus4CIndex); if (!snapshotHMinus4C.has_value()) { errorRet = strprintf("Can not find quorum snapshot at H-4C"); return false; @@ -303,7 +302,7 @@ bool BuildQuorumRotationInfo(CDeterministicMNManager& dmnman, const ChainstateMa return false; } - auto snapshotNeededH = quorumSnapshotManager->GetSnapshotForBlock(llmqType, pNeededBlockIndex); + auto snapshotNeededH = qsnapman.GetSnapshotForBlock(llmqType, pNeededBlockIndex); if (!snapshotNeededH.has_value()) { errorRet = strprintf("Can not find quorum snapshot at H(%d)", h); return false; diff --git a/src/llmq/snapshot.h b/src/llmq/snapshot.h index e1e32751c522b..b268c6db6e75f 100644 --- a/src/llmq/snapshot.h +++ b/src/llmq/snapshot.h @@ -207,7 +207,8 @@ class CQuorumRotationInfo [[nodiscard]] UniValue ToJson() const; }; -bool BuildQuorumRotationInfo(CDeterministicMNManager& dmnman, const ChainstateManager& chainman, const CQuorumManager& qman, +bool BuildQuorumRotationInfo(CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, + const ChainstateManager& chainman, const CQuorumManager& qman, const CQuorumBlockProcessor& qblockman, const CGetQuorumRotationInfo& request, CQuorumRotationInfo& response, std::string& errorRet) EXCLUSIVE_LOCKS_REQUIRED(::cs_main); uint256 GetLastBaseBlockHash(Span baseBlockIndexes, const CBlockIndex* blockIndex); @@ -228,9 +229,6 @@ class CQuorumSnapshotManager std::optional GetSnapshotForBlock(Consensus::LLMQType llmqType, const CBlockIndex* pindex); void StoreSnapshotForBlock(Consensus::LLMQType llmqType, const CBlockIndex* pindex, const CQuorumSnapshot& snapshot); }; - -extern std::unique_ptr quorumSnapshotManager; - } // namespace llmq #endif // BITCOIN_LLMQ_SNAPSHOT_H diff --git a/src/llmq/utils.cpp b/src/llmq/utils.cpp index a9bb1e3c81fec..7efdad91db587 100644 --- a/src/llmq/utils.cpp +++ b/src/llmq/utils.cpp @@ -24,12 +24,11 @@ #include class CBLSSignature; -namespace llmq -{ +namespace llmq { class CQuorum; using CQuorumPtr = std::shared_ptr; using CQuorumCPtr = std::shared_ptr; -} +} // namespace llmq /** * Forward declarations @@ -46,13 +45,9 @@ static bool IsV20Active(gsl::not_null pindexPrev) return DeploymentActiveAfter(pindexPrev, Params().GetConsensus(), Consensus::DEPLOYMENT_V20); } -namespace llmq -{ - -namespace utils - -{ -//QuorumMembers per quorumIndex at heights H-Cycle, H-2Cycles, H-3Cycles +namespace llmq { +namespace utils { +// QuorumMembers per quorumIndex at heights H-Cycle, H-2Cycles, H-3Cycles struct PreviousQuorumQuarters { std::vector> quarterHMinusC; std::vector> quarterHMinus2C; @@ -62,16 +57,33 @@ struct PreviousQuorumQuarters { }; // Forward declarations -static std::vector ComputeQuorumMembers(Consensus::LLMQType llmqType, CDeterministicMNManager& dmnman, const CBlockIndex* pQuorumBaseBlockIndex); -static std::vector> ComputeQuorumMembersByQuarterRotation(const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, const CBlockIndex* pCycleQuorumBaseBlockIndex); - -static std::vector> BuildNewQuorumQuarterMembers(const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, const CBlockIndex* pCycleQuorumBaseBlockIndex, const PreviousQuorumQuarters& quarters); - -static PreviousQuorumQuarters GetPreviousQuorumQuarterMembers(const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, const CBlockIndex* pBlockHMinusCIndex, const CBlockIndex* pBlockHMinus2CIndex, const CBlockIndex* pBlockHMinus3CIndex, int nHeight); -static std::vector> GetQuorumQuarterMembersBySnapshot(const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, const CBlockIndex* pCycleQuorumBaseBlockIndex, const llmq::CQuorumSnapshot& snapshot, int nHeights); -static std::pair GetMNUsageBySnapshot(const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, const CBlockIndex* pCycleQuorumBaseBlockIndex, const llmq::CQuorumSnapshot& snapshot, int nHeight); - -static void BuildQuorumSnapshot(const Consensus::LLMQParams& llmqParams, const CDeterministicMNList& allMns, const CDeterministicMNList& mnUsedAtH, std::vector& sortedCombinedMns, CQuorumSnapshot& quorumSnapshot, int nHeight, std::vector& skipList, const CBlockIndex* pCycleQuorumBaseBlockIndex); +static std::vector ComputeQuorumMembers(Consensus::LLMQType llmqType, CDeterministicMNManager& dmnman, + const CBlockIndex* pQuorumBaseBlockIndex); +static std::vector> ComputeQuorumMembersByQuarterRotation( + const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, + const CBlockIndex* pCycleQuorumBaseBlockIndex); + +static std::vector> BuildNewQuorumQuarterMembers( + const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, + const CBlockIndex* pCycleQuorumBaseBlockIndex, const PreviousQuorumQuarters& previousQuarters); + +static PreviousQuorumQuarters GetPreviousQuorumQuarterMembers(const Consensus::LLMQParams& llmqParams, + CDeterministicMNManager& dmnman, + CQuorumSnapshotManager& qsnapman, + const CBlockIndex* pBlockHMinusCIndex, + const CBlockIndex* pBlockHMinus2CIndex, + const CBlockIndex* pBlockHMinus3CIndex, int nHeight); +static std::vector> GetQuorumQuarterMembersBySnapshot( + const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, + const CBlockIndex* pCycleQuorumBaseBlockIndex, const llmq::CQuorumSnapshot& snapshot, int nHeight); +static std::pair GetMNUsageBySnapshot( + const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, + const CBlockIndex* pCycleQuorumBaseBlockIndex, const llmq::CQuorumSnapshot& snapshot, int nHeight); + +static void BuildQuorumSnapshot(const Consensus::LLMQParams& llmqParams, const CDeterministicMNList& allMns, + const CDeterministicMNList& mnUsedAtH, + std::vector& sortedCombinedMns, CQuorumSnapshot& quorumSnapshot, + int nHeight, std::vector& skipList, const CBlockIndex* pCycleQuorumBaseBlockIndex); static uint256 GetHashModifier(const Consensus::LLMQParams& llmqParams, gsl::not_null pCycleQuorumBaseBlockIndex) { @@ -97,7 +109,10 @@ static uint256 GetHashModifier(const Consensus::LLMQParams& llmqParams, gsl::not return ::SerializeHash(std::make_pair(llmqParams.type, pCycleQuorumBaseBlockIndex->GetBlockHash())); } -std::vector GetAllQuorumMembers(Consensus::LLMQType llmqType, CDeterministicMNManager& dmnman, gsl::not_null pQuorumBaseBlockIndex, bool reset_cache) +std::vector GetAllQuorumMembers(Consensus::LLMQType llmqType, CDeterministicMNManager& dmnman, + CQuorumSnapshotManager& qsnapman, + gsl::not_null pQuorumBaseBlockIndex, + bool reset_cache) { static RecursiveMutex cs_members; static std::map, StaticSaltedHasher>> mapQuorumMembers GUARDED_BY(cs_members); @@ -156,7 +171,7 @@ std::vector GetAllQuorumMembers(Consensus::LLMQType llmqTy return quorumMembers; } - auto q = ComputeQuorumMembersByQuarterRotation(llmq_params, dmnman, pCycleQuorumBaseBlockIndex); + auto q = ComputeQuorumMembersByQuarterRotation(llmq_params, dmnman, qsnapman, pCycleQuorumBaseBlockIndex); LOCK(cs_indexed_members); for (const size_t i : irange::range(q.size())) { mapIndexedQuorumMembers[llmqType].insert(std::make_pair(pCycleQuorumBaseBlockIndex->GetBlockHash(), i), q[i]); @@ -172,7 +187,8 @@ std::vector GetAllQuorumMembers(Consensus::LLMQType llmqTy return quorumMembers; } -std::vector ComputeQuorumMembers(Consensus::LLMQType llmqType, CDeterministicMNManager& dmnman, const CBlockIndex* pQuorumBaseBlockIndex) +std::vector ComputeQuorumMembers(Consensus::LLMQType llmqType, CDeterministicMNManager& dmnman, + const CBlockIndex* pQuorumBaseBlockIndex) { bool EvoOnly = (Params().GetConsensus().llmqTypePlatform == llmqType) && IsV19Active(pQuorumBaseBlockIndex); const auto& llmq_params_opt = Params().GetLLMQ(llmqType); @@ -190,7 +206,9 @@ std::vector ComputeQuorumMembers(Consensus::LLMQType llmqT return allMns.CalculateQuorum(llmq_params_opt->size, modifier, EvoOnly); } -std::vector> ComputeQuorumMembersByQuarterRotation(const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, const CBlockIndex* pCycleQuorumBaseBlockIndex) +std::vector> ComputeQuorumMembersByQuarterRotation( + const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, + const CBlockIndex* pCycleQuorumBaseBlockIndex) { const Consensus::LLMQType llmqType = llmqParams.type; @@ -207,12 +225,16 @@ std::vector> ComputeQuorumMembersByQuarterRota auto allMns = dmnman.GetListForBlock(pWorkBlockIndex); LogPrint(BCLog::LLMQ, "ComputeQuorumMembersByQuarterRotation llmqType[%d] nHeight[%d] allMns[%d]\n", ToUnderlying(llmqType), pCycleQuorumBaseBlockIndex->nHeight, allMns.GetValidMNsCount()); - PreviousQuorumQuarters previousQuarters = GetPreviousQuorumQuarterMembers(llmqParams, dmnman, pBlockHMinusCIndex, pBlockHMinus2CIndex, pBlockHMinus3CIndex, pCycleQuorumBaseBlockIndex->nHeight); + PreviousQuorumQuarters previousQuarters = GetPreviousQuorumQuarterMembers(llmqParams, dmnman, qsnapman, + pBlockHMinusCIndex, pBlockHMinus2CIndex, + pBlockHMinus3CIndex, + pCycleQuorumBaseBlockIndex->nHeight); size_t nQuorums = static_cast(llmqParams.signingActiveQuorumCount); std::vector> quorumMembers{nQuorums}; - auto newQuarterMembers = BuildNewQuorumQuarterMembers(llmqParams, dmnman, pCycleQuorumBaseBlockIndex, previousQuarters); + auto newQuarterMembers = BuildNewQuorumQuarterMembers(llmqParams, dmnman, qsnapman, pCycleQuorumBaseBlockIndex, + previousQuarters); //TODO Check if it is triggered from outside (P2P, block validation). Throwing an exception is probably a wiser choice //assert (!newQuarterMembers.empty()); @@ -265,28 +287,30 @@ std::vector> ComputeQuorumMembersByQuarterRota } PreviousQuorumQuarters GetPreviousQuorumQuarterMembers(const Consensus::LLMQParams& llmqParams, - CDeterministicMNManager& dmnman, + CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, const CBlockIndex* pBlockHMinusCIndex, const CBlockIndex* pBlockHMinus2CIndex, - const CBlockIndex* pBlockHMinus3CIndex, - int nHeight) + const CBlockIndex* pBlockHMinus3CIndex, int nHeight) { size_t nQuorums = static_cast(llmqParams.signingActiveQuorumCount); PreviousQuorumQuarters quarters{nQuorums}; - std::optional quSnapshotHMinusC = quorumSnapshotManager->GetSnapshotForBlock(llmqParams.type, pBlockHMinusCIndex); + std::optional quSnapshotHMinusC = qsnapman.GetSnapshotForBlock(llmqParams.type, + pBlockHMinusCIndex); if (quSnapshotHMinusC.has_value()) { quarters.quarterHMinusC = GetQuorumQuarterMembersBySnapshot(llmqParams, dmnman, pBlockHMinusCIndex, quSnapshotHMinusC.value(), nHeight); //TODO Check if it is triggered from outside (P2P, block validation). Throwing an exception is probably a wiser choice //assert (!quarterHMinusC.empty()); - std::optional quSnapshotHMinus2C = quorumSnapshotManager->GetSnapshotForBlock(llmqParams.type, pBlockHMinus2CIndex); + std::optional quSnapshotHMinus2C = qsnapman.GetSnapshotForBlock(llmqParams.type, + pBlockHMinus2CIndex); if (quSnapshotHMinus2C.has_value()) { quarters.quarterHMinus2C = GetQuorumQuarterMembersBySnapshot(llmqParams, dmnman, pBlockHMinus2CIndex, quSnapshotHMinus2C.value(), nHeight); //TODO Check if it is triggered from outside (P2P, block validation). Throwing an exception is probably a wiser choice //assert (!quarterHMinusC.empty()); - std::optional quSnapshotHMinus3C = quorumSnapshotManager->GetSnapshotForBlock(llmqParams.type, pBlockHMinus3CIndex); + std::optional quSnapshotHMinus3C = qsnapman.GetSnapshotForBlock(llmqParams.type, + pBlockHMinus3CIndex); if (quSnapshotHMinus3C.has_value()) { quarters.quarterHMinus3C = GetQuorumQuarterMembersBySnapshot(llmqParams, dmnman, pBlockHMinus3CIndex, quSnapshotHMinus3C.value(), nHeight); //TODO Check if it is triggered from outside (P2P, block validation). Throwing an exception is probably a wiser choice @@ -298,10 +322,9 @@ PreviousQuorumQuarters GetPreviousQuorumQuarterMembers(const Consensus::LLMQPara return quarters; } -std::vector> BuildNewQuorumQuarterMembers(const Consensus::LLMQParams& llmqParams, - CDeterministicMNManager& dmnman, - const CBlockIndex* pCycleQuorumBaseBlockIndex, - const PreviousQuorumQuarters& previousQuarters) +std::vector> BuildNewQuorumQuarterMembers( + const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, + const CBlockIndex* pCycleQuorumBaseBlockIndex, const PreviousQuorumQuarters& previousQuarters) { if (!llmqParams.useRotation || pCycleQuorumBaseBlockIndex->nHeight % llmqParams.dkgInterval != 0) { ASSERT_IF_DEBUG(false); @@ -454,14 +477,15 @@ std::vector> BuildNewQuorumQuarterMembers(cons BuildQuorumSnapshot(llmqParams, allMns, MnsUsedAtH, sortedCombinedMnsList, quorumSnapshot, pCycleQuorumBaseBlockIndex->nHeight, skipList, pCycleQuorumBaseBlockIndex); - quorumSnapshotManager->StoreSnapshotForBlock(llmqParams.type, pCycleQuorumBaseBlockIndex, quorumSnapshot); + qsnapman.StoreSnapshotForBlock(llmqParams.type, pCycleQuorumBaseBlockIndex, quorumSnapshot); return quarterQuorumMembers; } void BuildQuorumSnapshot(const Consensus::LLMQParams& llmqParams, const CDeterministicMNList& allMns, const CDeterministicMNList& mnUsedAtH, std::vector& sortedCombinedMns, - CQuorumSnapshot& quorumSnapshot, int nHeight, std::vector& skipList, const CBlockIndex* pCycleQuorumBaseBlockIndex) + CQuorumSnapshot& quorumSnapshot, int nHeight, std::vector& skipList, + const CBlockIndex* pCycleQuorumBaseBlockIndex) { if (!llmqParams.useRotation || pCycleQuorumBaseBlockIndex->nHeight % llmqParams.dkgInterval != 0) { ASSERT_IF_DEBUG(false); @@ -494,11 +518,9 @@ void BuildQuorumSnapshot(const Consensus::LLMQParams& llmqParams, const CDetermi } } -std::vector> GetQuorumQuarterMembersBySnapshot(const Consensus::LLMQParams& llmqParams, - CDeterministicMNManager& dmnman, - const CBlockIndex* pCycleQuorumBaseBlockIndex, - const llmq::CQuorumSnapshot& snapshot, - int nHeight) +std::vector> GetQuorumQuarterMembersBySnapshot( + const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, + const CBlockIndex* pCycleQuorumBaseBlockIndex, const llmq::CQuorumSnapshot& snapshot, int nHeight) { if (!llmqParams.useRotation || pCycleQuorumBaseBlockIndex->nHeight % llmqParams.dkgInterval != 0) { ASSERT_IF_DEBUG(false); @@ -654,11 +676,12 @@ uint256 DeterministicOutboundConnection(const uint256& proTxHash1, const uint256 } std::unordered_set GetQuorumConnections( - const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, const CSporkManager& sporkman, - gsl::not_null pQuorumBaseBlockIndex, const uint256& forMember, bool onlyOutbound) + const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, + const CSporkManager& sporkman, gsl::not_null pQuorumBaseBlockIndex, const uint256& forMember, + bool onlyOutbound) { if (IsAllMembersConnectedEnabled(llmqParams.type, sporkman)) { - auto mns = GetAllQuorumMembers(llmqParams.type, dmnman, pQuorumBaseBlockIndex); + auto mns = GetAllQuorumMembers(llmqParams.type, dmnman, qsnapman, pQuorumBaseBlockIndex); std::unordered_set result; for (const auto& dmn : mns) { @@ -675,15 +698,14 @@ std::unordered_set GetQuorumConnections( } return result; } - return GetQuorumRelayMembers(llmqParams, dmnman, pQuorumBaseBlockIndex, forMember, onlyOutbound); + return GetQuorumRelayMembers(llmqParams, dmnman, qsnapman, pQuorumBaseBlockIndex, forMember, onlyOutbound); } -std::unordered_set GetQuorumRelayMembers(const Consensus::LLMQParams& llmqParams, - CDeterministicMNManager& dmnman, - gsl::not_null pQuorumBaseBlockIndex, - const uint256& forMember, bool onlyOutbound) +std::unordered_set GetQuorumRelayMembers( + const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, + gsl::not_null pQuorumBaseBlockIndex, const uint256& forMember, bool onlyOutbound) { - auto mns = GetAllQuorumMembers(llmqParams.type, dmnman, pQuorumBaseBlockIndex); + auto mns = GetAllQuorumMembers(llmqParams.type, dmnman, qsnapman, pQuorumBaseBlockIndex); std::unordered_set result; auto calcOutbound = [&](size_t i, const uint256& proTxHash) { @@ -756,15 +778,17 @@ std::set CalcDeterministicWatchConnections(Consensus::LLMQType llmqType, return result; } -bool EnsureQuorumConnections(const Consensus::LLMQParams& llmqParams, CConnman& connman, CDeterministicMNManager& dmnman, const CSporkManager& sporkman, - const CDeterministicMNList& tip_mn_list, gsl::not_null pQuorumBaseBlockIndex, - const uint256& myProTxHash, bool is_masternode) +bool EnsureQuorumConnections(const Consensus::LLMQParams& llmqParams, CConnman& connman, + CDeterministicMNManager& dmnman, const CSporkManager& sporkman, + CQuorumSnapshotManager& qsnapman, const CDeterministicMNList& tip_mn_list, + gsl::not_null pQuorumBaseBlockIndex, const uint256& myProTxHash, + bool is_masternode) { if (!is_masternode && !IsWatchQuorumsEnabled()) { return false; } - auto members = GetAllQuorumMembers(llmqParams.type, dmnman, pQuorumBaseBlockIndex); + auto members = GetAllQuorumMembers(llmqParams.type, dmnman, qsnapman, pQuorumBaseBlockIndex); if (members.empty()) { return false; } @@ -781,8 +805,9 @@ bool EnsureQuorumConnections(const Consensus::LLMQParams& llmqParams, CConnman& std::unordered_set connections; std::unordered_set relayMembers; if (isMember) { - connections = GetQuorumConnections(llmqParams, dmnman, sporkman, pQuorumBaseBlockIndex, myProTxHash, true); - relayMembers = GetQuorumRelayMembers(llmqParams, dmnman, pQuorumBaseBlockIndex, myProTxHash, true); + connections = GetQuorumConnections(llmqParams, dmnman, qsnapman, sporkman, pQuorumBaseBlockIndex, myProTxHash, + true); + relayMembers = GetQuorumRelayMembers(llmqParams, dmnman, qsnapman, pQuorumBaseBlockIndex, myProTxHash, true); } else { auto cindexes = CalcDeterministicWatchConnections(llmqParams.type, pQuorumBaseBlockIndex, members.size(), 1); for (auto idx : cindexes) { @@ -813,8 +838,9 @@ bool EnsureQuorumConnections(const Consensus::LLMQParams& llmqParams, CConnman& } void AddQuorumProbeConnections(const Consensus::LLMQParams& llmqParams, CConnman& connman, CDeterministicMNManager& dmnman, - CMasternodeMetaMan& mn_metaman, const CSporkManager& sporkman, const CDeterministicMNList& tip_mn_list, - gsl::not_null pQuorumBaseBlockIndex, const uint256 &myProTxHash) + CMasternodeMetaMan& mn_metaman, CQuorumSnapshotManager& qsnapman, + const CSporkManager& sporkman, const CDeterministicMNList& tip_mn_list, + gsl::not_null pQuorumBaseBlockIndex, const uint256& myProTxHash) { assert(mn_metaman.IsValid()); @@ -822,7 +848,7 @@ void AddQuorumProbeConnections(const Consensus::LLMQParams& llmqParams, CConnman return; } - auto members = GetAllQuorumMembers(llmqParams.type, dmnman, pQuorumBaseBlockIndex); + auto members = GetAllQuorumMembers(llmqParams.type, dmnman, qsnapman, pQuorumBaseBlockIndex); auto curTime = GetTime().count(); std::set probeConnections; @@ -868,7 +894,5 @@ template void InitQuorumsCache, StaticSaltedHasher, 0ul, 0ul>, std::less, std::allocator, StaticSaltedHasher, 0ul, 0ul>>>>>(std::map, StaticSaltedHasher, 0ul, 0ul>, std::less, std::allocator, StaticSaltedHasher, 0ul, 0ul>>>>&cache, bool limit_by_connections); template void InitQuorumsCache>>(std::map>& cache, bool limit_by_connections); template void InitQuorumsCache>>(std::map>& cache, bool limit_by_connections); - } // namespace utils - } // namespace llmq diff --git a/src/llmq/utils.h b/src/llmq/utils.h index 2795db58dc1e0..01ed90c77db0d 100644 --- a/src/llmq/utils.h +++ b/src/llmq/utils.h @@ -26,37 +26,39 @@ class CSporkManager; using CDeterministicMNCPtr = std::shared_ptr; -namespace llmq -{ - -namespace utils -{ +namespace llmq { +class CQuorumSnapshotManager; +namespace utils { // includes members which failed DKG -std::vector GetAllQuorumMembers(Consensus::LLMQType llmqType, CDeterministicMNManager& dmnman, gsl::not_null pQuorumBaseBlockIndex, bool reset_cache = false); +std::vector GetAllQuorumMembers(Consensus::LLMQType llmqType, CDeterministicMNManager& dmnman, + CQuorumSnapshotManager& qsnapman, + gsl::not_null pQuorumBaseBlockIndex, + bool reset_cache = false); uint256 DeterministicOutboundConnection(const uint256& proTxHash1, const uint256& proTxHash2); std::unordered_set GetQuorumConnections( - const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, const CSporkManager& sporkman, + const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, + const CSporkManager& sporkman, gsl::not_null pQuorumBaseBlockIndex, const uint256& forMember, + bool onlyOutbound); +std::unordered_set GetQuorumRelayMembers( + const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, gsl::not_null pQuorumBaseBlockIndex, const uint256& forMember, bool onlyOutbound); -std::unordered_set GetQuorumRelayMembers(const Consensus::LLMQParams& llmqParams, - CDeterministicMNManager& dmnman, - gsl::not_null pQuorumBaseBlockIndex, - const uint256& forMember, bool onlyOutbound); std::set CalcDeterministicWatchConnections(Consensus::LLMQType llmqType, gsl::not_null pQuorumBaseBlockIndex, size_t memberCount, size_t connectionCount); -bool EnsureQuorumConnections(const Consensus::LLMQParams& llmqParams, CConnman& connman, CDeterministicMNManager& dmnman, const CSporkManager& sporkman, - const CDeterministicMNList& tip_mn_list, gsl::not_null pQuorumBaseBlockIndex, - const uint256& myProTxHash, bool is_masternode); +bool EnsureQuorumConnections(const Consensus::LLMQParams& llmqParams, CConnman& connman, + CDeterministicMNManager& dmnman, const CSporkManager& sporkman, + CQuorumSnapshotManager& qsnapman, const CDeterministicMNList& tip_mn_list, + gsl::not_null pQuorumBaseBlockIndex, const uint256& myProTxHash, + bool is_masternode); void AddQuorumProbeConnections(const Consensus::LLMQParams& llmqParams, CConnman& connman, CDeterministicMNManager& dmnman, - CMasternodeMetaMan& mn_metaman, const CSporkManager& sporkman, const CDeterministicMNList& tip_mn_list, + CMasternodeMetaMan& mn_metaman, CQuorumSnapshotManager& qsnapman, + const CSporkManager& sporkman, const CDeterministicMNList& tip_mn_list, gsl::not_null pQuorumBaseBlockIndex, const uint256& myProTxHash); template void InitQuorumsCache(CacheType& cache, bool limit_by_connections = true); - } // namespace utils - } // namespace llmq #endif // BITCOIN_LLMQ_UTILS_H diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 10ed771d6bf53..2753f2a354ec1 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -5205,7 +5205,7 @@ void PeerManagerImpl::ProcessMessage( llmq::CQuorumRotationInfo quorumRotationInfoRet; std::string strError; - if (BuildQuorumRotationInfo(*m_dmnman, m_chainman, *m_llmq_ctx->qman, *m_llmq_ctx->quorum_block_processor, cmd, quorumRotationInfoRet, strError)) { + if (BuildQuorumRotationInfo(*m_dmnman, *m_llmq_ctx->qsnapman, m_chainman, *m_llmq_ctx->qman, *m_llmq_ctx->quorum_block_processor, cmd, quorumRotationInfoRet, strError)) { m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::QUORUMROTATIONINFO, quorumRotationInfoRet)); } else { strError = strprintf("getquorumrotationinfo failed for size(baseBlockHashes)=%d, blockRequestHash=%s. error=%s", cmd.baseBlockHashes.size(), cmd.blockRequestHash.ToString(), strError); diff --git a/src/node/chainstate.cpp b/src/node/chainstate.cpp index beeee67477d88..d379a0ee6531d 100644 --- a/src/node/chainstate.cpp +++ b/src/node/chainstate.cpp @@ -4,6 +4,7 @@ #include +#include #include #include #include @@ -14,10 +15,7 @@ #include #include #include -#include #include -#include -#include std::optional LoadChainstate(bool fReset, ChainstateManager& chainman, @@ -31,9 +29,6 @@ std::optional LoadChainstate(bool fReset, std::unique_ptr& dmnman, std::unique_ptr& evodb, std::unique_ptr& mnhf_manager, - std::unique_ptr& clhandler, - std::unique_ptr& isman, - std::unique_ptr& qsnapman, std::unique_ptr& llmq_ctx, CTxMemPool* mempool, bool fPruneMode, @@ -66,7 +61,7 @@ std::optional LoadChainstate(bool fReset, mnhf_manager.reset(); mnhf_manager = std::make_unique(*evodb); - chainman.InitializeChainstate(mempool, *evodb, chain_helper, clhandler, isman); + chainman.InitializeChainstate(mempool, *evodb, chain_helper); chainman.m_total_coinstip_cache = nCoinCacheUsage; chainman.m_total_coinsdb_cache = nCoinDBCache; @@ -77,7 +72,7 @@ std::optional LoadChainstate(bool fReset, pblocktree.reset(new CBlockTreeDB(nBlockTreeDBCache, block_tree_db_in_memory, fReset)); DashChainstateSetup(chainman, govman, mn_metaman, mn_sync, sporkman, mn_activeman, chain_helper, cpoolman, - dmnman, evodb, mnhf_manager, qsnapman, llmq_ctx, mempool, fReset, fReindexChainState, + dmnman, evodb, mnhf_manager, llmq_ctx, mempool, fReset, fReindexChainState, consensus_params); if (fReset) { @@ -213,7 +208,6 @@ void DashChainstateSetup(ChainstateManager& chainman, std::unique_ptr& dmnman, std::unique_ptr& evodb, std::unique_ptr& mnhf_manager, - std::unique_ptr& qsnapman, std::unique_ptr& llmq_ctx, CTxMemPool* mempool, bool fReset, @@ -223,14 +217,10 @@ void DashChainstateSetup(ChainstateManager& chainman, // Same logic as pblocktree dmnman.reset(); dmnman = std::make_unique(chainman.ActiveChainstate(), *evodb); - mempool->ConnectManagers(dmnman.get()); cpoolman.reset(); cpoolman = std::make_unique(*evodb); - qsnapman.reset(); - qsnapman.reset(new llmq::CQuorumSnapshotManager(*evodb)); - if (llmq_ctx) { llmq_ctx->Interrupt(); llmq_ctx->Stop(); @@ -238,19 +228,20 @@ void DashChainstateSetup(ChainstateManager& chainman, llmq_ctx.reset(); llmq_ctx = std::make_unique(chainman, *dmnman, *evodb, mn_metaman, *mnhf_manager, sporkman, *mempool, mn_activeman.get(), mn_sync, /*unit_tests=*/false, /*wipe=*/fReset || fReindexChainState); + mempool->ConnectManagers(dmnman.get(), llmq_ctx->isman.get()); // Enable CMNHFManager::{Process, Undo}Block mnhf_manager->ConnectManagers(&chainman, llmq_ctx->qman.get()); chain_helper.reset(); - chain_helper = std::make_unique(*cpoolman, *dmnman, *mnhf_manager, govman, *(llmq_ctx->quorum_block_processor), chainman, - consensus_params, mn_sync, sporkman, *(llmq_ctx->clhandler), *(llmq_ctx->qman)); + chain_helper = std::make_unique(*cpoolman, *dmnman, *mnhf_manager, govman, *(llmq_ctx->isman), *(llmq_ctx->quorum_block_processor), + *(llmq_ctx->qsnapman), chainman, consensus_params, mn_sync, sporkman, *(llmq_ctx->clhandler), + *(llmq_ctx->qman)); } void DashChainstateSetupClose(std::unique_ptr& chain_helper, std::unique_ptr& cpoolman, std::unique_ptr& dmnman, std::unique_ptr& mnhf_manager, - std::unique_ptr& qsnapman, std::unique_ptr& llmq_ctx, CTxMemPool* mempool) @@ -260,7 +251,6 @@ void DashChainstateSetupClose(std::unique_ptr& chain_helper, mnhf_manager->DisconnectManagers(); } llmq_ctx.reset(); - qsnapman.reset(); cpoolman.reset(); mempool->DisconnectManagers(); dmnman.reset(); diff --git a/src/node/chainstate.h b/src/node/chainstate.h index aa507b5af374d..c7b399177e412 100644 --- a/src/node/chainstate.h +++ b/src/node/chainstate.h @@ -25,12 +25,6 @@ class CSporkManager; class CTxMemPool; struct LLMQContext; -namespace llmq { -class CChainLocksHandler; -class CInstantSendManager; -class CQuorumSnapshotManager; -} - namespace Consensus { struct Params; } @@ -93,9 +87,6 @@ std::optional LoadChainstate(bool fReset, std::unique_ptr& dmnman, std::unique_ptr& evodb, std::unique_ptr& mnhf_manager, - std::unique_ptr& clhandler, - std::unique_ptr& isman, - std::unique_ptr& qsnapman, std::unique_ptr& llmq_ctx, CTxMemPool* mempool, bool fPruneMode, @@ -127,7 +118,6 @@ void DashChainstateSetup(ChainstateManager& chainman, std::unique_ptr& dmnman, std::unique_ptr& evodb, std::unique_ptr& mnhf_manager, - std::unique_ptr& qsnapman, std::unique_ptr& llmq_ctx, CTxMemPool* mempool, bool fReset, @@ -138,7 +128,6 @@ void DashChainstateSetupClose(std::unique_ptr& chain_helper, std::unique_ptr& cpoolman, std::unique_ptr& dmnman, std::unique_ptr& mnhf_manager, - std::unique_ptr& qsnapman, std::unique_ptr& llmq_ctx, CTxMemPool* mempool); diff --git a/src/node/miner.cpp b/src/node/miner.cpp index 48fff3d3e2921..46518ae8ef109 100644 --- a/src/node/miner.cpp +++ b/src/node/miner.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -75,6 +76,7 @@ BlockAssembler::BlockAssembler(CChainState& chainstate, const NodeContext& node, m_mnhfman(*Assert(node.mnhf_manager)), m_clhandler(*Assert(Assert(node.llmq_ctx)->clhandler)), m_isman(*Assert(Assert(node.llmq_ctx)->isman)), + m_qsnapman(*Assert(Assert(node.llmq_ctx)->qsnapman)), chainparams(params), m_mempool(mempool), m_quorum_block_processor(*Assert(Assert(node.llmq_ctx)->quorum_block_processor)), @@ -222,7 +224,7 @@ std::unique_ptr BlockAssembler::CreateNewBlock(const CScript& sc cbTx.nHeight = nHeight; BlockValidationState state; - if (!CalcCbTxMerkleRootMNList(*pblock, pindexPrev, cbTx.merkleRootMNList, m_dmnman, state, m_chainstate.CoinsTip())) { + if (!CalcCbTxMerkleRootMNList(*pblock, pindexPrev, cbTx.merkleRootMNList, state, m_dmnman, m_qsnapman, m_chainstate.CoinsTip())) { throw std::runtime_error(strprintf("%s: CalcCbTxMerkleRootMNList failed: %s", __func__, state.ToString())); } if (fDIP0008Active_context) { diff --git a/src/node/miner.h b/src/node/miner.h index b7654a7d34f82..10919cadb7477 100644 --- a/src/node/miner.h +++ b/src/node/miner.h @@ -38,6 +38,7 @@ class CChainLocksHandler; class CInstantSendManager; class CQuorumBlockProcessor; class CQuorumManager; +class CQuorumSnapshotManager; } // namespace llmq static const bool DEFAULT_PRINTPRIORITY = false; @@ -174,6 +175,7 @@ class BlockAssembler CMNHFManager& m_mnhfman; llmq::CChainLocksHandler& m_clhandler; llmq::CInstantSendManager& m_isman; + llmq::CQuorumSnapshotManager& m_qsnapman; const CChainParams& chainparams; const CTxMemPool& m_mempool; const llmq::CQuorumBlockProcessor& m_quorum_block_processor; diff --git a/src/rest.cpp b/src/rest.cpp index 961891c49b316..a144b71cf139f 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -132,6 +132,27 @@ static ChainstateManager* GetChainman(const CoreContext& context, HTTPRequest* r return node_context->chainman.get(); } +/** + * Get the node context LLMQContext. + * + * @param[in] req The HTTP request, whose status code will be set if node + * context LLMQContext is not found. + * @returns Pointer to the LLMQContext or nullptr if none found. + */ +static LLMQContext* GetLLMQContext(const CoreContext& context, HTTPRequest* req) +{ + auto node_context = GetContext(context); + if (!node_context || !node_context->llmq_ctx) { + RESTERR(req, HTTP_INTERNAL_SERVER_ERROR, + strprintf("%s:%d (%s)\n" + "Internal bug detected: LLMQ context not found!\n" + "You may report this issue here: %s\n", + __FILE__, __LINE__, __func__, PACKAGE_BUGREPORT)); + return nullptr; + } + return node_context->llmq_ctx.get(); +} + static RetFormat ParseDataFormat(std::string& param, const std::string& strReq) { const std::string::size_type pos = strReq.rfind('.'); @@ -247,9 +268,12 @@ static bool rest_headers(const CoreContext& context, return true; } case RetFormat::JSON: { + const LLMQContext* llmq_ctx = GetLLMQContext(context, req); + if (!llmq_ctx) return false; + UniValue jsonHeaders(UniValue::VARR); for (const CBlockIndex *pindex : headers) { - jsonHeaders.push_back(blockheaderToJSON(tip, pindex, *llmq::chainLocksHandler)); + jsonHeaders.push_back(blockheaderToJSON(tip, pindex, *llmq_ctx->clhandler)); } std::string strJSON = jsonHeaders.write() + "\n"; req->WriteHeader("Content-Type", "application/json"); @@ -317,7 +341,10 @@ static bool rest_block(const CoreContext& context, } case RetFormat::JSON: { - UniValue objBlock = blockToJSON(chainman.m_blockman, block, tip, pblockindex, *llmq::chainLocksHandler, *llmq::quorumInstantSendManager, showTxDetails); + const LLMQContext* llmq_ctx = GetLLMQContext(context, req); + if (!llmq_ctx) return false; + + UniValue objBlock = blockToJSON(chainman.m_blockman, block, tip, pblockindex, *llmq_ctx->clhandler, *llmq_ctx->isman, showTxDetails); std::string strJSON = objBlock.write() + "\n"; req->WriteHeader("Content-Type", "application/json"); req->WriteReply(HTTP_OK, strJSON); @@ -580,7 +607,10 @@ static bool rest_mempool_info(const CoreContext& context, HTTPRequest* req, cons switch (rf) { case RetFormat::JSON: { - UniValue mempoolInfoObject = MempoolInfoToJSON(*mempool, *llmq::quorumInstantSendManager); + const LLMQContext* llmq_ctx = GetLLMQContext(context, req); + if (!llmq_ctx) return false; + + UniValue mempoolInfoObject = MempoolInfoToJSON(*mempool, *llmq_ctx->isman); std::string strJSON = mempoolInfoObject.write() + "\n"; req->WriteHeader("Content-Type", "application/json"); @@ -603,7 +633,10 @@ static bool rest_mempool_contents(const CoreContext& context, HTTPRequest* req, switch (rf) { case RetFormat::JSON: { - UniValue mempoolObject = MempoolToJSON(*mempool, llmq::quorumInstantSendManager.get(), true); + const LLMQContext* llmq_ctx = GetLLMQContext(context, req); + if (!llmq_ctx) return false; + + UniValue mempoolObject = MempoolToJSON(*mempool, llmq_ctx->isman.get(), true); std::string strJSON = mempoolObject.write() + "\n"; req->WriteHeader("Content-Type", "application/json"); diff --git a/src/rpc/mempool.cpp b/src/rpc/mempool.cpp index ca1c3af5d0f63..3aa482e42e23d 100644 --- a/src/rpc/mempool.cpp +++ b/src/rpc/mempool.cpp @@ -201,7 +201,7 @@ RPCHelpMan getrawmempool() const CTxMemPool& mempool = EnsureMemPool(node); const LLMQContext& llmq_ctx = EnsureLLMQContext(node); - return MempoolToJSON(mempool, llmq_ctx.isman, fVerbose, include_mempool_sequence); + return MempoolToJSON(mempool, llmq_ctx.isman.get(), fVerbose, include_mempool_sequence); }, }; } @@ -264,7 +264,7 @@ RPCHelpMan getmempoolancestors() const CTxMemPoolEntry &e = *ancestorIt; const uint256& _hash = e.GetTx().GetHash(); UniValue info(UniValue::VOBJ); - entryToJSON(mempool, info, e, llmq_ctx.isman); + entryToJSON(mempool, info, e, llmq_ctx.isman.get()); o.pushKV(_hash.ToString(), info); } return o; @@ -332,7 +332,7 @@ RPCHelpMan getmempooldescendants() const CTxMemPoolEntry &e = *descendantIt; const uint256& _hash = e.GetTx().GetHash(); UniValue info(UniValue::VOBJ); - entryToJSON(mempool, info, e, llmq_ctx.isman); + entryToJSON(mempool, info, e, llmq_ctx.isman.get()); o.pushKV(_hash.ToString(), info); } return o; @@ -372,7 +372,7 @@ RPCHelpMan getmempoolentry() const CTxMemPoolEntry &e = *it; UniValue info(UniValue::VOBJ); const LLMQContext& llmq_ctx = EnsureLLMQContext(node); - entryToJSON(mempool, info, e, llmq_ctx.isman); + entryToJSON(mempool, info, e, llmq_ctx.isman.get()); return info; }, }; diff --git a/src/rpc/quorums.cpp b/src/rpc/quorums.cpp index e7da6e4a03ec5..bd2a4c82ab874 100644 --- a/src/rpc/quorums.cpp +++ b/src/rpc/quorums.cpp @@ -296,7 +296,7 @@ static RPCHelpMan quorum_dkgstatus() llmq::CDKGDebugStatus status; llmq_ctx.dkg_debugman->GetLocalDebugStatus(status); - auto ret = status.ToJson(*CHECK_NONFATAL(node.dmnman), chainman, detailLevel); + auto ret = status.ToJson(*CHECK_NONFATAL(node.dmnman), *llmq_ctx.qsnapman, chainman, detailLevel); CBlockIndex* pindexTip = WITH_LOCK(cs_main, return chainman.ActiveChain().Tip()); int tipHeight = pindexTip->nHeight; @@ -324,8 +324,12 @@ static RPCHelpMan quorum_dkgstatus() obj.pushKV("quorumHash", pQuorumBaseBlockIndex->GetBlockHash().ToString()); obj.pushKV("pindexTip", pindexTip->nHeight); - auto allConnections = llmq::utils::GetQuorumConnections(llmq_params, *node.dmnman, *node.sporkman, pQuorumBaseBlockIndex, proTxHash, false); - auto outboundConnections = llmq::utils::GetQuorumConnections(llmq_params, *node.dmnman, *node.sporkman, pQuorumBaseBlockIndex, proTxHash, true); + auto allConnections = llmq::utils::GetQuorumConnections(llmq_params, *node.dmnman, + *llmq_ctx.qsnapman, *node.sporkman, + pQuorumBaseBlockIndex, proTxHash, false); + auto outboundConnections = llmq::utils::GetQuorumConnections(llmq_params, *node.dmnman, + *llmq_ctx.qsnapman, *node.sporkman, + pQuorumBaseBlockIndex, proTxHash, true); std::map foundConnections; connman.ForEachNode([&](const CNode* pnode) { auto verifiedProRegTxHash = pnode->GetVerifiedProRegTxHash(); @@ -859,8 +863,8 @@ static RPCHelpMan quorum_rotationinfo() LOCK(cs_main); - if (!BuildQuorumRotationInfo(*CHECK_NONFATAL(node.dmnman), chainman, *llmq_ctx.qman, *llmq_ctx.quorum_block_processor, - cmd, quorumRotationInfoRet, strError)) { + if (!BuildQuorumRotationInfo(*CHECK_NONFATAL(node.dmnman), *llmq_ctx.qsnapman, chainman, *llmq_ctx.qman, + *llmq_ctx.quorum_block_processor, cmd, quorumRotationInfoRet, strError)) { throw JSONRPCError(RPC_INVALID_REQUEST, strError); } diff --git a/src/test/evo_deterministicmns_tests.cpp b/src/test/evo_deterministicmns_tests.cpp index 8783081f9c7d6..0f4133fba900f 100644 --- a/src/test/evo_deterministicmns_tests.cpp +++ b/src/test/evo_deterministicmns_tests.cpp @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include @@ -653,7 +655,7 @@ void FuncTestMempoolReorg(TestChainSetup& setup) CTxMemPool testPool; if (setup.m_node.dmnman) { - testPool.ConnectManagers(setup.m_node.dmnman.get()); + testPool.ConnectManagers(setup.m_node.dmnman.get(), setup.m_node.llmq_ctx->isman.get()); } TestMemPoolEntryHelper entry; LOCK2(cs_main, testPool.cs); @@ -727,7 +729,7 @@ void FuncTestMempoolDualProregtx(TestChainSetup& setup) CTxMemPool testPool; if (setup.m_node.dmnman) { - testPool.ConnectManagers(setup.m_node.dmnman.get()); + testPool.ConnectManagers(setup.m_node.dmnman.get(), setup.m_node.llmq_ctx->isman.get()); } TestMemPoolEntryHelper entry; LOCK2(cs_main, testPool.cs); diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index edf088a0392ac..eb34f1d3fa7d7 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -12,21 +12,9 @@ #include #include #include -#include -#include #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include #include @@ -41,8 +29,6 @@ #include #include