diff --git a/doc/release-notes-6078.md b/doc/release-notes-6078.md new file mode 100644 index 0000000000000..1350e0c36817f --- /dev/null +++ b/doc/release-notes-6078.md @@ -0,0 +1,4 @@ +RPC changes +----------- + +- The following RPCs, `protx list`, `protx listdiff`, `protx info` will no longer report `collateralAddress` if the transaction index has been disabled (`txindex=0`). diff --git a/src/bench/coin_selection.cpp b/src/bench/coin_selection.cpp index 3b82351928b2f..9f1a75a553425 100644 --- a/src/bench/coin_selection.cpp +++ b/src/bench/coin_selection.cpp @@ -61,10 +61,6 @@ static void CoinSelection(benchmark::Bench& bench) } typedef std::set CoinSet; -static NodeContext testNode; -static auto testChain = interfaces::MakeChain(testNode); -static CWallet testWallet(testChain.get(), /*coinjoin_loader=*/ nullptr, "", CreateDummyWalletDatabase()); -std::vector> wtxn; // Copied from src/wallet/test/coinselector_tests.cpp static void add_coin(const CAmount& nValue, int nInput, std::vector& set) @@ -72,10 +68,9 @@ static void add_coin(const CAmount& nValue, int nInput, std::vector CMutableTransaction tx; tx.vout.resize(nInput + 1); tx.vout[nInput].nValue = nValue; - std::unique_ptr wtx = std::make_unique(&testWallet, MakeTransactionRef(std::move(tx))); + CInputCoin coin(MakeTransactionRef(tx), nInput); set.emplace_back(); - set.back().Insert(COutput(wtx.get(), nInput, 0, true, true, true).GetInputCoin(), 0, true, 0, 0, false); - wtxn.emplace_back(std::move(wtx)); + set.back().Insert(coin, 0, true, 0, 0, false); } // Copied from src/wallet/test/coinselector_tests.cpp static CAmount make_hard_case(int utxos, std::vector& utxo_pool) @@ -93,7 +88,6 @@ static CAmount make_hard_case(int utxos, std::vector& utxo_pool) static void BnBExhaustion(benchmark::Bench& bench) { // Setup - testWallet.SetupLegacyScriptPubKeyMan(); std::vector utxo_pool; CoinSet selection; CAmount value_ret = 0; diff --git a/src/bench/duplicate_inputs.cpp b/src/bench/duplicate_inputs.cpp index 173a2faca9027..11fbd361785ae 100644 --- a/src/bench/duplicate_inputs.cpp +++ b/src/bench/duplicate_inputs.cpp @@ -25,7 +25,6 @@ static void DuplicateInputs(benchmark::Bench& bench) CMutableTransaction coinbaseTx{}; CMutableTransaction naughtyTx{}; - assert(std::addressof(::ChainActive()) == std::addressof(testing_setup->m_node.chainman->ActiveChain())); CBlockIndex* pindexPrev = testing_setup->m_node.chainman->ActiveChain().Tip(); assert(pindexPrev != nullptr); block.nBits = GetNextWorkRequired(pindexPrev, &block, chainparams.GetConsensus()); diff --git a/src/coinjoin/client.cpp b/src/coinjoin/client.cpp index 4f35c0b8f0afe..7498b1524d227 100644 --- a/src/coinjoin/client.cpp +++ b/src/coinjoin/client.cpp @@ -131,7 +131,7 @@ PeerMsgRet CCoinJoinClientQueueManager::ProcessDSQueue(const CNode& peer, CDataS return {}; } -void CCoinJoinClientManager::ProcessMessage(CNode& peer, CConnman& connman, const CTxMemPool& mempool, std::string_view msg_type, CDataStream& vRecv) +void CCoinJoinClientManager::ProcessMessage(CNode& peer, CChainState& active_chainstate, CConnman& connman, const CTxMemPool& mempool, std::string_view msg_type, CDataStream& vRecv) { if (m_is_masternode) return; if (!CCoinJoinClientOptions::IsEnabled()) return; @@ -150,7 +150,7 @@ void CCoinJoinClientManager::ProcessMessage(CNode& peer, CConnman& connman, cons AssertLockNotHeld(cs_deqsessions); LOCK(cs_deqsessions); for (auto& session : deqSessions) { - session.ProcessMessage(peer, connman, mempool, msg_type, vRecv); + session.ProcessMessage(peer, active_chainstate, connman, mempool, msg_type, vRecv); } } } @@ -167,7 +167,7 @@ CCoinJoinClientSession::CCoinJoinClientSession(CWallet& wallet, CoinJoinWalletMa m_is_masternode{is_masternode} {} -void CCoinJoinClientSession::ProcessMessage(CNode& peer, CConnman& connman, const CTxMemPool& mempool, std::string_view msg_type, CDataStream& vRecv) +void CCoinJoinClientSession::ProcessMessage(CNode& peer, CChainState& active_chainstate, CConnman& connman, const CTxMemPool& mempool, std::string_view msg_type, CDataStream& vRecv) { if (m_is_masternode) return; if (!CCoinJoinClientOptions::IsEnabled()) return; @@ -202,7 +202,7 @@ void CCoinJoinClientSession::ProcessMessage(CNode& peer, CConnman& connman, cons WalletCJLogPrint(m_wallet, "DSFINALTX -- txNew %s", txNew.ToString()); /* Continued */ // check to see if input is spent already? (and probably not confirmed) - SignFinalTransaction(mempool, txNew, peer, connman); + SignFinalTransaction(peer, active_chainstate, connman, mempool, txNew); } else if (msg_type == NetMsgType::DSCOMPLETE) { if (!mixingMasternode) return; @@ -548,7 +548,7 @@ void CCoinJoinClientSession::ProcessPoolStateUpdate(CCoinJoinStatusUpdate psssup // check it to make sure it's what we want, then sign it if we agree. // If we refuse to sign, it's possible we'll be charged collateral // -bool CCoinJoinClientSession::SignFinalTransaction(const CTxMemPool& mempool, const CTransaction& finalTransactionNew, CNode& peer, CConnman& connman) +bool CCoinJoinClientSession::SignFinalTransaction(CNode& peer, CChainState& active_chainstate, CConnman& connman, const CTxMemPool& mempool, const CTransaction& finalTransactionNew) { if (!CCoinJoinClientOptions::IsEnabled()) return false; @@ -577,7 +577,7 @@ bool CCoinJoinClientSession::SignFinalTransaction(const CTxMemPool& mempool, con // Make sure all inputs/outputs are valid PoolMessage nMessageID{MSG_NOERR}; - if (!IsValidInOuts(mempool, finalMutableTransaction.vin, finalMutableTransaction.vout, nMessageID, nullptr)) { + if (!IsValidInOuts(active_chainstate, 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(); @@ -781,7 +781,7 @@ bool CCoinJoinClientManager::CheckAutomaticBackup() // // Passively run mixing in the background to mix funds based on the given configuration. // -bool CCoinJoinClientSession::DoAutomaticDenominating(CConnman& connman, CTxMemPool& mempool, bool fDryRun) +bool CCoinJoinClientSession::DoAutomaticDenominating(CChainState& active_chainstate, CConnman& connman, CTxMemPool& mempool, bool fDryRun) { if (m_is_masternode) return false; // no client-side mixing on masternodes if (nState != POOL_STATE_IDLE) return false; @@ -934,7 +934,7 @@ bool CCoinJoinClientSession::DoAutomaticDenominating(CConnman& connman, CTxMemPo return false; } } else { - if (!CoinJoin::IsCollateralValid(mempool, CTransaction(txMyCollateral))) { + if (!CoinJoin::IsCollateralValid(active_chainstate, 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); @@ -961,7 +961,7 @@ bool CCoinJoinClientSession::DoAutomaticDenominating(CConnman& connman, CTxMemPo return false; } -bool CCoinJoinClientManager::DoAutomaticDenominating(CConnman& connman, CTxMemPool& mempool, bool fDryRun) +bool CCoinJoinClientManager::DoAutomaticDenominating(CChainState& active_chainstate, CConnman& connman, CTxMemPool& mempool, bool fDryRun) { if (m_is_masternode) return false; // no client-side mixing on masternodes if (!CCoinJoinClientOptions::IsEnabled() || !IsMixing()) return false; @@ -1003,7 +1003,7 @@ bool CCoinJoinClientManager::DoAutomaticDenominating(CConnman& connman, CTxMemPo return false; } - fResult &= session.DoAutomaticDenominating(connman, mempool, fDryRun); + fResult &= session.DoAutomaticDenominating(active_chainstate, connman, mempool, fDryRun); } return fResult; @@ -1840,7 +1840,7 @@ void CCoinJoinClientQueueManager::DoMaintenance() CheckQueue(); } -void CCoinJoinClientManager::DoMaintenance(CConnman& connman, CTxMemPool& mempool) +void CCoinJoinClientManager::DoMaintenance(CChainState& active_chainstate, CConnman& connman, CTxMemPool& mempool) { if (!CCoinJoinClientOptions::IsEnabled()) return; if (m_is_masternode) return; // no client-side mixing on masternodes @@ -1854,7 +1854,7 @@ void CCoinJoinClientManager::DoMaintenance(CConnman& connman, CTxMemPool& mempoo CheckTimeout(); ProcessPendingDsaRequest(connman); if (nDoAutoNextRun == nTick) { - DoAutomaticDenominating(connman, mempool); + DoAutomaticDenominating(active_chainstate, connman, mempool); nDoAutoNextRun = nTick + COINJOIN_AUTO_TIMEOUT_MIN + GetRandInt(COINJOIN_AUTO_TIMEOUT_MAX - COINJOIN_AUTO_TIMEOUT_MIN); } } @@ -1901,9 +1901,10 @@ void CoinJoinWalletManager::Add(CWallet& wallet) { void CoinJoinWalletManager::DoMaintenance() { for (auto& [wallet_str, walletman] : m_wallet_manager_map) { - walletman->DoMaintenance(m_connman, m_mempool); + walletman->DoMaintenance(m_chainstate, m_connman, m_mempool); } } + void CoinJoinWalletManager::Remove(const std::string& name) { m_wallet_manager_map.erase(name); g_wallet_init_interface.InitCoinJoinSettings(*this); diff --git a/src/coinjoin/client.h b/src/coinjoin/client.h index 40a633fc483f4..ba77e565cf264 100644 --- a/src/coinjoin/client.h +++ b/src/coinjoin/client.h @@ -73,10 +73,10 @@ class CoinJoinWalletManager { using wallet_name_cjman_map = std::map>; public: - CoinJoinWalletManager(CConnman& connman, CDeterministicMNManager& dmnman, CMasternodeMetaMan& mn_metaman, CTxMemPool& mempool, + CoinJoinWalletManager(CChainState& chainstate, CConnman& connman, CDeterministicMNManager& dmnman, CMasternodeMetaMan& mn_metaman, CTxMemPool& mempool, const CMasternodeSync& mn_sync, const std::unique_ptr& queueman, bool is_masternode) - : m_connman(connman), m_dmnman(dmnman), m_mn_metaman(mn_metaman), m_mempool(mempool), m_mn_sync(mn_sync), m_queueman(queueman), - m_is_masternode{is_masternode} + : m_chainstate(chainstate), m_connman(connman), m_dmnman(dmnman), m_mn_metaman(mn_metaman), m_mempool(mempool), m_mn_sync(mn_sync), + m_queueman(queueman), m_is_masternode{is_masternode} {} ~CoinJoinWalletManager() { @@ -96,6 +96,7 @@ class CoinJoinWalletManager { const wallet_name_cjman_map& raw() const { return m_wallet_manager_map; } private: + CChainState& m_chainstate; CConnman& m_connman; CDeterministicMNManager& m_dmnman; CMasternodeMetaMan& m_mn_metaman; @@ -160,7 +161,7 @@ class CCoinJoinClientSession : public CCoinJoinBaseSession void CompletedTransaction(PoolMessage nMessageID); /// As a client, check and sign the final transaction - bool SignFinalTransaction(const CTxMemPool& mempool, const CTransaction& finalTransactionNew, CNode& peer, CConnman& connman) EXCLUSIVE_LOCKS_REQUIRED(!cs_coinjoin); + bool SignFinalTransaction(CNode& peer, CChainState& active_chainstate, CConnman& connman, const CTxMemPool& mempool, const CTransaction& finalTransactionNew) EXCLUSIVE_LOCKS_REQUIRED(!cs_coinjoin); void RelayIn(const CCoinJoinEntry& entry, CConnman& connman) const; @@ -170,7 +171,7 @@ class CCoinJoinClientSession : public CCoinJoinBaseSession explicit CCoinJoinClientSession(CWallet& wallet, CoinJoinWalletManager& walletman, CDeterministicMNManager& dmnman, CMasternodeMetaMan& mn_metaman, const CMasternodeSync& mn_sync, const std::unique_ptr& queueman, bool is_masternode); - void ProcessMessage(CNode& peer, CConnman& connman, const CTxMemPool& mempool, std::string_view msg_type, CDataStream& vRecv); + void ProcessMessage(CNode& peer, CChainState& active_chainstate, CConnman& connman, const CTxMemPool& mempool, std::string_view msg_type, CDataStream& vRecv); void UnlockCoins(); @@ -181,7 +182,7 @@ class CCoinJoinClientSession : public CCoinJoinBaseSession bool GetMixingMasternodeInfo(CDeterministicMNCPtr& ret) const; /// Passively run mixing in the background according to the configuration in settings - bool DoAutomaticDenominating(CConnman& connman, CTxMemPool& mempool, bool fDryRun = false) EXCLUSIVE_LOCKS_REQUIRED(!cs_coinjoin); + bool DoAutomaticDenominating(CChainState& active_chainstate, CConnman& connman, CTxMemPool& mempool, bool fDryRun = false) EXCLUSIVE_LOCKS_REQUIRED(!cs_coinjoin); /// As a client, submit part of a future mixing transaction to a Masternode to start the process bool SubmitDenominate(CConnman& connman); @@ -267,7 +268,7 @@ class CCoinJoinClientManager m_wallet(wallet), m_walletman(walletman), m_dmnman(dmnman), m_mn_metaman(mn_metaman), m_mn_sync(mn_sync), m_queueman(queueman), m_is_masternode{is_masternode} {} - void ProcessMessage(CNode& peer, CConnman& connman, const CTxMemPool& mempool, std::string_view msg_type, CDataStream& vRecv) EXCLUSIVE_LOCKS_REQUIRED(!cs_deqsessions); + void ProcessMessage(CNode& peer, CChainState& active_chainstate, CConnman& connman, const CTxMemPool& mempool, std::string_view msg_type, CDataStream& vRecv) EXCLUSIVE_LOCKS_REQUIRED(!cs_deqsessions); bool StartMixing(); void StopMixing(); @@ -280,7 +281,7 @@ class CCoinJoinClientManager bool GetMixingMasternodesInfo(std::vector& vecDmnsRet) const EXCLUSIVE_LOCKS_REQUIRED(!cs_deqsessions); /// Passively run mixing in the background according to the configuration in settings - bool DoAutomaticDenominating(CConnman& connman, CTxMemPool& mempool, bool fDryRun = false) EXCLUSIVE_LOCKS_REQUIRED(!cs_deqsessions); + bool DoAutomaticDenominating(CChainState& active_chainstate, CConnman& connman, CTxMemPool& mempool, bool fDryRun = false) EXCLUSIVE_LOCKS_REQUIRED(!cs_deqsessions); bool TrySubmitDenominate(const CService& mnAddr, CConnman& connman) EXCLUSIVE_LOCKS_REQUIRED(!cs_deqsessions); bool MarkAlreadyJoinedQueueAsTried(CCoinJoinQueue& dsq) const EXCLUSIVE_LOCKS_REQUIRED(!cs_deqsessions); @@ -296,7 +297,7 @@ class CCoinJoinClientManager void UpdatedBlockTip(const CBlockIndex* pindex); - void DoMaintenance(CConnman& connman, CTxMemPool& mempool) EXCLUSIVE_LOCKS_REQUIRED(!cs_deqsessions); + void DoMaintenance(CChainState& active_chainstate, CConnman& connman, CTxMemPool& mempool) EXCLUSIVE_LOCKS_REQUIRED(!cs_deqsessions); void GetJsonInfo(UniValue& obj) const EXCLUSIVE_LOCKS_REQUIRED(!cs_deqsessions); }; diff --git a/src/coinjoin/coinjoin.cpp b/src/coinjoin/coinjoin.cpp index 8ab741e28fb88..75120cda40261 100644 --- a/src/coinjoin/coinjoin.cpp +++ b/src/coinjoin/coinjoin.cpp @@ -217,7 +217,7 @@ std::string CCoinJoinBaseSession::GetStateString() const } } -bool CCoinJoinBaseSession::IsValidInOuts(const CTxMemPool& mempool, const std::vector& vin, const std::vector& vout, PoolMessage& nMessageIDRet, bool* fConsumeCollateralRet) const +bool CCoinJoinBaseSession::IsValidInOuts(CChainState& active_chainstate, const CTxMemPool& mempool, const std::vector& vin, const std::vector& vout, PoolMessage& nMessageIDRet, bool* fConsumeCollateralRet) const { std::set setScripPubKeys; nMessageIDRet = MSG_NOERR; @@ -264,7 +264,7 @@ bool CCoinJoinBaseSession::IsValidInOuts(const CTxMemPool& mempool, const std::v nFees -= txout.nValue; } - CCoinsViewMemPool viewMemPool(WITH_LOCK(cs_main, return &::ChainstateActive().CoinsTip()), mempool); + CCoinsViewMemPool viewMemPool(WITH_LOCK(cs_main, return &active_chainstate.CoinsTip()), mempool); for (const auto& txin : vin) { LogPrint(BCLog::COINJOIN, "CCoinJoinBaseSession::%s -- txin=%s\n", __func__, txin.ToString()); @@ -322,7 +322,7 @@ bool ATMPIfSaneFee(CChainState& active_chainstate, CTxMemPool& pool, const CTran } // check to make sure the collateral provided by the client is valid -bool CoinJoin::IsCollateralValid(CTxMemPool& mempool, const CTransaction& txCollateral) +bool CoinJoin::IsCollateralValid(CChainState& active_chainstate, CTxMemPool& mempool, const CTransaction& txCollateral) { if (txCollateral.vout.empty()) return false; if (txCollateral.nLockTime != 0) return false; @@ -348,7 +348,7 @@ bool CoinJoin::IsCollateralValid(CTxMemPool& mempool, const CTransaction& txColl return false; } nValueIn += mempoolTx->vout[txin.prevout.n].nValue; - } else if (GetUTXOCoin(txin.prevout, coin)) { + } else if (GetUTXOCoin(active_chainstate, txin.prevout, coin)) { nValueIn += coin.out.nValue; } else { LogPrint(BCLog::COINJOIN, "CoinJoin::IsCollateralValid -- Unknown inputs in collateral transaction, txCollateral=%s", txCollateral.ToString()); /* Continued */ @@ -366,7 +366,7 @@ bool CoinJoin::IsCollateralValid(CTxMemPool& mempool, const CTransaction& txColl { LOCK(cs_main); - if (!ATMPIfSaneFee(::ChainstateActive(), mempool, MakeTransactionRef(txCollateral), /*test_accept=*/true)) { + if (!ATMPIfSaneFee(active_chainstate, mempool, MakeTransactionRef(txCollateral), /*test_accept=*/true)) { LogPrint(BCLog::COINJOIN, "CoinJoin::IsCollateralValid -- didn't pass AcceptToMemoryPool()\n"); return false; } diff --git a/src/coinjoin/coinjoin.h b/src/coinjoin/coinjoin.h index 06dd934a83f63..8fc3127fcc59a 100644 --- a/src/coinjoin/coinjoin.h +++ b/src/coinjoin/coinjoin.h @@ -309,7 +309,7 @@ class CCoinJoinBaseSession virtual void SetNull() EXCLUSIVE_LOCKS_REQUIRED(cs_coinjoin); - bool IsValidInOuts(const CTxMemPool& mempool, const std::vector& vin, const std::vector& vout, PoolMessage& nMessageIDRet, bool* fConsumeCollateralRet) const; + bool IsValidInOuts(CChainState& active_chainstate, 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 @@ -354,7 +354,7 @@ namespace CoinJoin constexpr CAmount GetMaxPoolAmount() { return COINJOIN_ENTRY_MAX_SIZE * vecStandardDenominations.front(); } /// If the collateral is valid given by a client - bool IsCollateralValid(CTxMemPool& mempool, const CTransaction& txCollateral); + bool IsCollateralValid(CChainState& active_chainstate, CTxMemPool& mempool, const CTransaction& txCollateral); } diff --git a/src/coinjoin/context.cpp b/src/coinjoin/context.cpp index f8a47466cfc69..c6f24fe9cb885 100644 --- a/src/coinjoin/context.cpp +++ b/src/coinjoin/context.cpp @@ -14,7 +14,7 @@ CJContext::CJContext(CChainState& chainstate, CConnman& connman, CDeterministicM const std::unique_ptr& peerman, bool relay_txes) : dstxman{std::make_unique()}, #ifdef ENABLE_WALLET - walletman{std::make_unique(connman, dmnman, mn_metaman, mempool, mn_sync, queueman, /* is_masternode = */ mn_activeman != nullptr)}, + walletman{std::make_unique(chainstate, connman, dmnman, mn_metaman, mempool, mn_sync, queueman, /* is_masternode = */ mn_activeman != nullptr)}, queueman {relay_txes ? std::make_unique(connman, *walletman, dmnman, mn_metaman, mn_sync, /* is_masternode = */ mn_activeman != nullptr) : nullptr}, #endif // ENABLE_WALLET server{std::make_unique(chainstate, connman, dmnman, *dstxman, mn_metaman, mempool, mn_activeman, mn_sync, peerman)} diff --git a/src/coinjoin/server.cpp b/src/coinjoin/server.cpp index a3b7a8c61e739..935e5b6f0c4c8 100644 --- a/src/coinjoin/server.cpp +++ b/src/coinjoin/server.cpp @@ -574,7 +574,7 @@ bool CCoinJoinServer::AddEntry(const CCoinJoinEntry& entry, PoolMessage& nMessag return false; } - if (!CoinJoin::IsCollateralValid(mempool, *entry.txCollateral)) { + if (!CoinJoin::IsCollateralValid(m_chainstate, mempool, *entry.txCollateral)) { LogPrint(BCLog::COINJOIN, "CCoinJoinServer::%s -- ERROR: collateral not valid!\n", __func__); nMessageIDRet = ERR_INVALID_COLLATERAL; return false; @@ -608,7 +608,7 @@ bool CCoinJoinServer::AddEntry(const CCoinJoinEntry& entry, PoolMessage& nMessag } bool fConsumeCollateral{false}; - if (!IsValidInOuts(mempool, vin, entry.vecTxOut, nMessageIDRet, &fConsumeCollateral)) { + if (!IsValidInOuts(m_chainstate, 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); @@ -685,7 +685,7 @@ bool CCoinJoinServer::IsAcceptableDSA(const CCoinJoinAccept& dsa, PoolMessage& n } // check collateral - if (!fUnitTest && !CoinJoin::IsCollateralValid(mempool, CTransaction(dsa.txCollateral))) { + if (!fUnitTest && !CoinJoin::IsCollateralValid(m_chainstate, mempool, CTransaction(dsa.txCollateral))) { LogPrint(BCLog::COINJOIN, "CCoinJoinServer::%s -- collateral not valid!\n", __func__); nMessageIDRet = ERR_INVALID_COLLATERAL; return false; diff --git a/src/dsnotificationinterface.cpp b/src/dsnotificationinterface.cpp index 45931a633b04f..0741ecc91b7b3 100644 --- a/src/dsnotificationinterface.cpp +++ b/src/dsnotificationinterface.cpp @@ -28,6 +28,7 @@ CDSNotificationInterface::CDSNotificationInterface(CConnman& connman, CMasternodeSync& mn_sync, CGovernanceManager& govman, PeerManager& peerman, + const ChainstateManager& chainman, const CActiveMasternodeManager* const mn_activeman, const std::unique_ptr& dmnman, const std::unique_ptr& llmq_ctx, @@ -36,6 +37,7 @@ CDSNotificationInterface::CDSNotificationInterface(CConnman& connman, m_mn_sync(mn_sync), m_govman(govman), m_peerman(peerman), + m_chainman(chainman), m_mn_activeman(mn_activeman), m_dmnman(dmnman), m_llmq_ctx(llmq_ctx), @@ -43,8 +45,8 @@ CDSNotificationInterface::CDSNotificationInterface(CConnman& connman, void CDSNotificationInterface::InitializeCurrentBlockTip() { - SynchronousUpdatedBlockTip(::ChainActive().Tip(), nullptr, ::ChainstateActive().IsInitialBlockDownload()); - UpdatedBlockTip(::ChainActive().Tip(), nullptr, ::ChainstateActive().IsInitialBlockDownload()); + SynchronousUpdatedBlockTip(m_chainman.ActiveChain().Tip(), nullptr, m_chainman.ActiveChainstate().IsInitialBlockDownload()); + UpdatedBlockTip(m_chainman.ActiveChain().Tip(), nullptr, m_chainman.ActiveChainstate().IsInitialBlockDownload()); } void CDSNotificationInterface::AcceptedBlockHeader(const CBlockIndex *pindexNew) diff --git a/src/dsnotificationinterface.h b/src/dsnotificationinterface.h index b715217ac118e..dc4456de40579 100644 --- a/src/dsnotificationinterface.h +++ b/src/dsnotificationinterface.h @@ -11,6 +11,7 @@ class CActiveMasternodeManager; class CConnman; class CDeterministicMNManager; class CGovernanceManager; +class ChainstateManager; class CMasternodeSync; class PeerManager; struct CJContext; @@ -23,6 +24,7 @@ class CDSNotificationInterface : public CValidationInterface CMasternodeSync& mn_sync, CGovernanceManager& govman, PeerManager& peerman, + const ChainstateManager& chainman, const CActiveMasternodeManager* const mn_activeman, const std::unique_ptr& dmnman, const std::unique_ptr& llmq_ctx, @@ -50,6 +52,7 @@ class CDSNotificationInterface : public CValidationInterface CMasternodeSync& m_mn_sync; CGovernanceManager& m_govman; PeerManager& m_peerman; + const ChainstateManager& m_chainman; const CActiveMasternodeManager* const m_mn_activeman; const std::unique_ptr& m_dmnman; const std::unique_ptr& m_llmq_ctx; diff --git a/src/evo/assetlocktx.cpp b/src/evo/assetlocktx.cpp index df67e459ebece..ccbb0042e023e 100644 --- a/src/evo/assetlocktx.cpp +++ b/src/evo/assetlocktx.cpp @@ -22,13 +22,13 @@ /** * Common code for Asset Lock and Asset Unlock */ -bool CheckAssetLockUnlockTx(const llmq::CQuorumManager& qman, const CTransaction& tx, gsl::not_null pindexPrev, const std::optional& indexes, TxValidationState& state) +bool CheckAssetLockUnlockTx(const BlockManager& blockman, const llmq::CQuorumManager& qman, const CTransaction& tx, gsl::not_null pindexPrev, const std::optional& indexes, TxValidationState& state) { switch (tx.nType) { case TRANSACTION_ASSET_LOCK: return CheckAssetLockTx(tx, state); case TRANSACTION_ASSET_UNLOCK: - return CheckAssetUnlockTx(qman, tx, pindexPrev, indexes, state); + return CheckAssetUnlockTx(blockman, qman, tx, pindexPrev, indexes, state); default: return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-not-asset-locks-at-all"); } @@ -141,7 +141,7 @@ bool CAssetUnlockPayload::VerifySig(const llmq::CQuorumManager& qman, const uint return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-assetunlock-not-verified"); } -bool CheckAssetUnlockTx(const llmq::CQuorumManager& qman, const CTransaction& tx, gsl::not_null pindexPrev, const std::optional& indexes, TxValidationState& state) +bool CheckAssetUnlockTx(const BlockManager& blockman, const llmq::CQuorumManager& qman, const CTransaction& tx, gsl::not_null pindexPrev, const std::optional& indexes, TxValidationState& state) { // Some checks depends from blockchain status also, such as `known indexes` and `withdrawal limits` // They are omitted here and done by CCreditPool @@ -171,7 +171,7 @@ bool CheckAssetUnlockTx(const llmq::CQuorumManager& qman, const CTransaction& tx return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-assetunlock-duplicated-index"); } - if (LOCK(cs_main); g_chainman.m_blockman.LookupBlockIndex(assetUnlockTx.getQuorumHash()) == nullptr) { + if (LOCK(cs_main); blockman.LookupBlockIndex(assetUnlockTx.getQuorumHash()) == nullptr) { return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-assetunlock-quorum-hash"); } diff --git a/src/evo/assetlocktx.h b/src/evo/assetlocktx.h index b3fff47fa64f7..ff4853fb3571d 100644 --- a/src/evo/assetlocktx.h +++ b/src/evo/assetlocktx.h @@ -14,6 +14,7 @@ #include +class BlockManager; class CBlockIndex; class CRangesSet; class TxValidationState; @@ -172,8 +173,8 @@ class CAssetUnlockPayload }; bool CheckAssetLockTx(const CTransaction& tx, TxValidationState& state); -bool CheckAssetUnlockTx(const llmq::CQuorumManager& qman, const CTransaction& tx, gsl::not_null pindexPrev, const std::optional& indexes, TxValidationState& state); -bool CheckAssetLockUnlockTx(const llmq::CQuorumManager& qman, const CTransaction& tx, gsl::not_null pindexPrev, const std::optional& indexes, TxValidationState& state); +bool CheckAssetUnlockTx(const BlockManager& blockman, const llmq::CQuorumManager& qman, const CTransaction& tx, gsl::not_null pindexPrev, const std::optional& indexes, TxValidationState& state); +bool CheckAssetLockUnlockTx(const BlockManager& blockman, const llmq::CQuorumManager& qman, const CTransaction& tx, gsl::not_null pindexPrev, const std::optional& indexes, TxValidationState& state); bool GetAssetUnlockFee(const CTransaction& tx, CAmount& txfee, TxValidationState& state); #endif // BITCOIN_EVO_ASSETLOCKTX_H diff --git a/src/evo/chainhelper.cpp b/src/evo/chainhelper.cpp index 519983b84697d..4c6a6ab964694 100644 --- a/src/evo/chainhelper.cpp +++ b/src/evo/chainhelper.cpp @@ -9,11 +9,11 @@ #include CChainstateHelper::CChainstateHelper(CCreditPoolManager& cpoolman, CDeterministicMNManager& dmnman, CMNHFManager& mnhfman, CGovernanceManager& govman, - llmq::CQuorumBlockProcessor& qblockman, const Consensus::Params& consensus_params, + 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, consensus_params, mn_sync, sporkman)}, - special_tx{std::make_unique(cpoolman, dmnman, mnhfman, qblockman, consensus_params, clhandler, 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() = default; diff --git a/src/evo/chainhelper.h b/src/evo/chainhelper.h index 4e687b3f28079..73db5b3427e6a 100644 --- a/src/evo/chainhelper.h +++ b/src/evo/chainhelper.h @@ -9,6 +9,7 @@ class CCreditPoolManager; class CDeterministicMNManager; +class ChainstateManager; class CMNHFManager; class CMNPaymentsProcessor; class CMasternodeSync; @@ -27,7 +28,7 @@ class CChainstateHelper { public: explicit CChainstateHelper(CCreditPoolManager& cpoolman, CDeterministicMNManager& dmnman, CMNHFManager& mnhfman, CGovernanceManager& govman, - llmq::CQuorumBlockProcessor& qblockman, const Consensus::Params& consensus_params, + 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); ~CChainstateHelper(); diff --git a/src/evo/creditpool.cpp b/src/evo/creditpool.cpp index fbea65f5ef1b1..876b9bfb3aa4a 100644 --- a/src/evo/creditpool.cpp +++ b/src/evo/creditpool.cpp @@ -267,12 +267,12 @@ bool CCreditPoolDiff::Unlock(const CTransaction& tx, TxValidationState& state) return true; } -bool CCreditPoolDiff::ProcessLockUnlockTransaction(const llmq::CQuorumManager& qman, const CTransaction& tx, TxValidationState& state) +bool CCreditPoolDiff::ProcessLockUnlockTransaction(const BlockManager& blockman, const llmq::CQuorumManager& qman, const CTransaction& tx, TxValidationState& state) { if (!tx.IsSpecialTxVersion()) return true; if (tx.nType != TRANSACTION_ASSET_LOCK && tx.nType != TRANSACTION_ASSET_UNLOCK) return true; - if (!CheckAssetLockUnlockTx(qman, tx, pindexPrev, pool.indexes, state)) { + if (!CheckAssetLockUnlockTx(blockman, qman, tx, pindexPrev, pool.indexes, state)) { // pass the state returned by the function above return false; } @@ -292,8 +292,9 @@ bool CCreditPoolDiff::ProcessLockUnlockTransaction(const llmq::CQuorumManager& q } } -std::optional GetCreditPoolDiffForBlock(CCreditPoolManager& cpoolman, const llmq::CQuorumManager& qman, const CBlock& block, const CBlockIndex* pindexPrev, - const Consensus::Params& consensusParams, const CAmount blockSubsidy, BlockValidationState& state) +std::optional GetCreditPoolDiffForBlock(CCreditPoolManager& cpoolman, const BlockManager& blockman, const llmq::CQuorumManager& qman, + const CBlock& block, const CBlockIndex* pindexPrev, const Consensus::Params& consensusParams, + const CAmount blockSubsidy, BlockValidationState& state) { try { const CCreditPool creditPool = cpoolman.GetCreditPool(pindexPrev, consensusParams); @@ -302,7 +303,7 @@ std::optional GetCreditPoolDiffForBlock(CCreditPoolManager& cpo for (size_t i = 1; i < block.vtx.size(); ++i) { const auto& tx = *block.vtx[i]; TxValidationState tx_state; - if (!creditPoolDiff.ProcessLockUnlockTransaction(qman, tx, tx_state)) { + if (!creditPoolDiff.ProcessLockUnlockTransaction(blockman, qman, tx, tx_state)) { assert(tx_state.GetResult() == TxValidationResult::TX_CONSENSUS); state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, tx_state.GetRejectReason(), strprintf("Process Lock/Unlock Transaction failed at Credit Pool (tx hash %s) %s", tx.GetHash().ToString(), tx_state.GetDebugMessage())); diff --git a/src/evo/creditpool.h b/src/evo/creditpool.h index 13b113f31b5f0..479cc77879553 100644 --- a/src/evo/creditpool.h +++ b/src/evo/creditpool.h @@ -20,6 +20,7 @@ #include #include +class BlockManager; class CBlockIndex; class BlockValidationState; class TxValidationState; @@ -83,7 +84,7 @@ class CCreditPoolDiff { * to change amount of credit pool * @return true if transaction can be included in this block */ - bool ProcessLockUnlockTransaction(const llmq::CQuorumManager& qman, const CTransaction& tx, TxValidationState& state); + bool ProcessLockUnlockTransaction(const BlockManager& blockman, const llmq::CQuorumManager& qman, const CTransaction& tx, TxValidationState& state); /** * this function returns total amount of credits for the next block @@ -135,7 +136,8 @@ class CCreditPoolManager CCreditPool ConstructCreditPool(const CBlockIndex* block_index, CCreditPool prev, const Consensus::Params& consensusParams); }; -std::optional GetCreditPoolDiffForBlock(CCreditPoolManager& cpoolman, const llmq::CQuorumManager& qman, const CBlock& block, const CBlockIndex* pindexPrev, - const Consensus::Params& consensusParams, const CAmount blockSubsidy, BlockValidationState& state); +std::optional GetCreditPoolDiffForBlock(CCreditPoolManager& cpoolman, const BlockManager& blockman, const llmq::CQuorumManager& qman, + const CBlock& block, const CBlockIndex* pindexPrev, const Consensus::Params& consensusParams, + const CAmount blockSubsidy, BlockValidationState& state); #endif diff --git a/src/evo/deterministicmns.cpp b/src/evo/deterministicmns.cpp index fc2146e22755f..b35dab60a9804 100644 --- a/src/evo/deterministicmns.cpp +++ b/src/evo/deterministicmns.cpp @@ -49,17 +49,13 @@ UniValue CDeterministicMN::ToJson() const obj.pushKV("collateralHash", collateralOutpoint.hash.ToString()); obj.pushKV("collateralIndex", (int)collateralOutpoint.n); - CScript scriptPubKey; - if (Coin coin; GetUTXOCoin(collateralOutpoint, coin)) { - scriptPubKey = coin.out.scriptPubKey; - } else { - uint256 tmpHashBlock; - CTransactionRef collateralTx = GetTransaction(/* block_index */ nullptr, /* mempool */ nullptr, collateralOutpoint.hash, Params().GetConsensus(), tmpHashBlock); - scriptPubKey = collateralTx->vout[collateralOutpoint.n].scriptPubKey; - } - CTxDestination dest; - if (ExtractDestination(scriptPubKey, dest)) { - obj.pushKV("collateralAddress", EncodeDestination(dest)); + uint256 tmpHashBlock; + CTransactionRef collateralTx = GetTransaction(/* block_index */ nullptr, /* mempool */ nullptr, collateralOutpoint.hash, Params().GetConsensus(), tmpHashBlock); + if (collateralTx) { + CTxDestination dest; + if (ExtractDestination(collateralTx->vout[collateralOutpoint.n].scriptPubKey, dest)) { + obj.pushKV("collateralAddress", EncodeDestination(dest)); + } } obj.pushKV("operatorReward", (double)nOperatorReward / 100); diff --git a/src/evo/mnauth.cpp b/src/evo/mnauth.cpp index 9e9de36f9718c..854574a0337cd 100644 --- a/src/evo/mnauth.cpp +++ b/src/evo/mnauth.cpp @@ -61,7 +61,8 @@ void CMNAuth::PushMNAUTH(CNode& peer, CConnman& connman, const CActiveMasternode } PeerMsgRet CMNAuth::ProcessMessage(CNode& peer, CConnman& connman, CMasternodeMetaMan& mn_metaman, const CActiveMasternodeManager* const mn_activeman, - const CMasternodeSync& mn_sync, const CDeterministicMNList& tip_mn_list, std::string_view msg_type, CDataStream& vRecv) + const CChain& active_chain, const CMasternodeSync& mn_sync, const CDeterministicMNList& tip_mn_list, + std::string_view msg_type, CDataStream& vRecv) { assert(mn_metaman.IsValid()); @@ -105,7 +106,7 @@ PeerMsgRet CMNAuth::ProcessMessage(CNode& peer, CConnman& connman, CMasternodeMe if (Params().NetworkIDString() != CBaseChainParams::MAIN && gArgs.IsArgSet("-pushversion")) { nOurNodeVersion = gArgs.GetArg("-pushversion", PROTOCOL_VERSION); } - const CBlockIndex* tip = ::ChainActive().Tip(); + const CBlockIndex* tip = active_chain.Tip(); const bool is_basic_scheme_active{DeploymentActiveAfter(tip, Params().GetConsensus(), Consensus::DEPLOYMENT_V19)}; ConstCBLSPublicKeyVersionWrapper pubKey(dmn->pdmnState->pubKeyOperator.Get(), !is_basic_scheme_active); // See comment in PushMNAUTH (fInbound is negated here as we're on the other side of the connection) diff --git a/src/evo/mnauth.h b/src/evo/mnauth.h index 211dae0cf20cc..802b8e64f1d8a 100644 --- a/src/evo/mnauth.h +++ b/src/evo/mnauth.h @@ -11,6 +11,7 @@ class CActiveMasternodeManager; class CBlockIndex; +class CChain; class CConnman; class CDataStream; class CDeterministicMN; @@ -59,7 +60,8 @@ class CMNAuth * attempting to call this function regardless of sync state */ static PeerMsgRet ProcessMessage(CNode& peer, CConnman& connman, CMasternodeMetaMan& mn_metaman, const CActiveMasternodeManager* const mn_activeman, - const CMasternodeSync& mn_sync, const CDeterministicMNList& tip_mn_list, std::string_view msg_type, CDataStream& vRecv); + const CChain& active_chain, const CMasternodeSync& mn_sync, const CDeterministicMNList& tip_mn_list, + std::string_view msg_type, CDataStream& vRecv); static void NotifyMasternodeListChanged(bool undo, const CDeterministicMNList& oldMNList, const CDeterministicMNListDiff& diff, CConnman& connman); }; diff --git a/src/evo/mnhftx.cpp b/src/evo/mnhftx.cpp index 8f1a14d92bb53..02f1839f087fb 100644 --- a/src/evo/mnhftx.cpp +++ b/src/evo/mnhftx.cpp @@ -101,7 +101,7 @@ bool MNHFTx::Verify(const llmq::CQuorumManager& qman, const uint256& quorumHash, return true; } -bool CheckMNHFTx(const llmq::CQuorumManager& qman, const CTransaction& tx, const CBlockIndex* pindexPrev, TxValidationState& state) +bool CheckMNHFTx(const ChainstateManager& chainman, const llmq::CQuorumManager& qman, const CTransaction& tx, const CBlockIndex* pindexPrev, TxValidationState& state) { if (!tx.IsSpecialTxVersion() || tx.nType != TRANSACTION_MNHF_SIGNAL) { return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-mnhf-type"); @@ -116,7 +116,7 @@ bool CheckMNHFTx(const llmq::CQuorumManager& qman, const CTransaction& tx, const return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-mnhf-version"); } - const CBlockIndex* pindexQuorum = WITH_LOCK(::cs_main, return g_chainman.m_blockman.LookupBlockIndex(mnhfTx.signal.quorumHash)); + const CBlockIndex* pindexQuorum = WITH_LOCK(::cs_main, return chainman.m_blockman.LookupBlockIndex(mnhfTx.signal.quorumHash)); if (!pindexQuorum) { return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-mnhf-quorum-hash"); } @@ -160,7 +160,7 @@ std::optional extractEHFSignal(const CTransaction& tx) return opt_mnhfTx->signal.versionBit; } -static bool extractSignals(const llmq::CQuorumManager& qman, const CBlock& block, const CBlockIndex* const pindex, std::vector& new_signals, BlockValidationState& state) +static bool extractSignals(const ChainstateManager& chainman, const llmq::CQuorumManager& qman, const CBlock& block, const CBlockIndex* const pindex, std::vector& new_signals, BlockValidationState& state) { // we skip the coinbase for (size_t i = 1; i < block.vtx.size(); ++i) { @@ -172,7 +172,7 @@ static bool extractSignals(const llmq::CQuorumManager& qman, const CBlock& block } TxValidationState tx_state; - if (!CheckMNHFTx(qman, tx, pindex, tx_state)) { + if (!CheckMNHFTx(chainman, qman, tx, pindex, tx_state)) { return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, tx_state.GetRejectReason(), tx_state.GetDebugMessage()); } @@ -192,11 +192,11 @@ static bool extractSignals(const llmq::CQuorumManager& qman, const CBlock& block std::optional CMNHFManager::ProcessBlock(const CBlock& block, const CBlockIndex* const pindex, bool fJustCheck, BlockValidationState& state) { - assert(m_qman); + assert(m_chainman && m_qman); try { std::vector new_signals; - if (!extractSignals(*m_qman, block, pindex, new_signals, state)) { + if (!extractSignals(*m_chainman, *m_qman, block, pindex, new_signals, state)) { // state is set inside extractSignals return std::nullopt; } @@ -246,11 +246,11 @@ std::optional CMNHFManager::ProcessBlock(const CBlock& bl bool CMNHFManager::UndoBlock(const CBlock& block, const CBlockIndex* const pindex) { - assert(m_qman); + assert(m_chainman && m_qman); std::vector excluded_signals; BlockValidationState state; - if (!extractSignals(*m_qman, block, pindex, excluded_signals, state)) { + if (!extractSignals(*m_chainman, *m_qman, block, pindex, excluded_signals, state)) { LogPrintf("CMNHFManager::%s: failed to extract signals\n", __func__); return false; } @@ -354,10 +354,11 @@ void CMNHFManager::AddSignal(const CBlockIndex* const pindex, int bit) AddToCache(signals, pindex); } -void CMNHFManager::ConnectManagers(gsl::not_null qman) +void CMNHFManager::ConnectManagers(gsl::not_null chainman, gsl::not_null qman) { // Do not allow double-initialization - assert(m_qman == nullptr); + assert(m_chainman == nullptr && m_qman == nullptr); + m_chainman = chainman; m_qman = qman; } diff --git a/src/evo/mnhftx.h b/src/evo/mnhftx.h index 53425d60ab288..a6386203dc1e0 100644 --- a/src/evo/mnhftx.h +++ b/src/evo/mnhftx.h @@ -22,6 +22,7 @@ class BlockValidationState; class CBlock; class CBlockIndex; class CEvoDB; +class ChainstateManager; class TxValidationState; namespace llmq { class CQuorumManager; @@ -100,6 +101,7 @@ class CMNHFManager : public AbstractEHFManager { private: CEvoDB& m_evoDb; + ChainstateManager* m_chainman{nullptr}; llmq::CQuorumManager* m_qman{nullptr}; static constexpr size_t MNHFCacheSize = 1000; @@ -147,14 +149,14 @@ class CMNHFManager : public AbstractEHFManager * Separated from constructor to allow LLMQContext to use CMNHFManager in read-only capacity. * Required to mutate state. */ - void ConnectManagers(gsl::not_null qman); + void ConnectManagers(gsl::not_null chainman, gsl::not_null qman); /** * Reset llmq::CQuorumManager pointer. * * @pre Must be called before LLMQContext (containing llmq::CQuorumManager) is destroyed. */ - void DisconnectManagers() { m_qman = nullptr; }; + void DisconnectManagers() { m_chainman = nullptr; m_qman = nullptr; }; private: void AddToCache(const Signals& signals, const CBlockIndex* const pindex); @@ -175,6 +177,6 @@ class CMNHFManager : public AbstractEHFManager }; std::optional extractEHFSignal(const CTransaction& tx); -bool CheckMNHFTx(const llmq::CQuorumManager& qman, const CTransaction& tx, const CBlockIndex* pindexPrev, TxValidationState& state); +bool CheckMNHFTx(const ChainstateManager& chainman, const llmq::CQuorumManager& qman, const CTransaction& tx, const CBlockIndex* pindexPrev, TxValidationState& state); #endif // BITCOIN_EVO_MNHFTX_H diff --git a/src/evo/simplifiedmns.cpp b/src/evo/simplifiedmns.cpp index bc80c1dd68341..41c3138c66526 100644 --- a/src/evo/simplifiedmns.cpp +++ b/src/evo/simplifiedmns.cpp @@ -316,29 +316,29 @@ CSimplifiedMNListDiff BuildSimplifiedDiff(const CDeterministicMNList& from, cons return diffRet; } -bool BuildSimplifiedMNListDiff(const uint256& baseBlockHash, const uint256& blockHash, CSimplifiedMNListDiff& mnListDiffRet, - CDeterministicMNManager& dmnman, const llmq::CQuorumBlockProcessor& quorum_block_processor, const llmq::CQuorumManager& qman, - std::string& errorRet, bool extended) +bool BuildSimplifiedMNListDiff(CDeterministicMNManager& dmnman, const ChainstateManager& chainman, const llmq::CQuorumBlockProcessor& qblockman, + const llmq::CQuorumManager& qman, const uint256& baseBlockHash, const uint256& blockHash, + CSimplifiedMNListDiff& mnListDiffRet, std::string& errorRet, bool extended) { AssertLockHeld(cs_main); mnListDiffRet = CSimplifiedMNListDiff(); - const CBlockIndex* baseBlockIndex = ::ChainActive().Genesis(); + const CBlockIndex* baseBlockIndex = chainman.ActiveChain().Genesis(); if (!baseBlockHash.IsNull()) { - baseBlockIndex = g_chainman.m_blockman.LookupBlockIndex(baseBlockHash); + baseBlockIndex = chainman.m_blockman.LookupBlockIndex(baseBlockHash); if (!baseBlockIndex) { errorRet = strprintf("block %s not found", baseBlockHash.ToString()); return false; } } - const CBlockIndex* blockIndex = g_chainman.m_blockman.LookupBlockIndex(blockHash); + const CBlockIndex* blockIndex = chainman.m_blockman.LookupBlockIndex(blockHash); if (!blockIndex) { errorRet = strprintf("block %s not found", blockHash.ToString()); return false; } - if (!::ChainActive().Contains(baseBlockIndex) || !::ChainActive().Contains(blockIndex)) { + if (!chainman.ActiveChain().Contains(baseBlockIndex) || !chainman.ActiveChain().Contains(blockIndex)) { errorRet = strprintf("block %s and %s are not in the same chain", baseBlockHash.ToString(), blockHash.ToString()); return false; } @@ -356,7 +356,7 @@ bool BuildSimplifiedMNListDiff(const uint256& baseBlockHash, const uint256& bloc // null block hash was provided to get the diff from the genesis block. mnListDiffRet.baseBlockHash = baseBlockHash; - if (!mnListDiffRet.BuildQuorumsDiff(baseBlockIndex, blockIndex, quorum_block_processor)) { + if (!mnListDiffRet.BuildQuorumsDiff(baseBlockIndex, blockIndex, qblockman)) { errorRet = strprintf("failed to build quorums diff"); return false; } diff --git a/src/evo/simplifiedmns.h b/src/evo/simplifiedmns.h index 47e4c105f9547..ed894f9ff227d 100644 --- a/src/evo/simplifiedmns.h +++ b/src/evo/simplifiedmns.h @@ -16,6 +16,7 @@ class UniValue; class CBlockIndex; class CDeterministicMNList; class CDeterministicMN; +class ChainstateManager; namespace llmq { class CFinalCommitment; @@ -170,8 +171,8 @@ class CSimplifiedMNListDiff [[nodiscard]] UniValue ToJson(bool extended = false) const; }; -bool BuildSimplifiedMNListDiff(const uint256& baseBlockHash, const uint256& blockHash, CSimplifiedMNListDiff& mnListDiffRet, - CDeterministicMNManager& dmnman, const llmq::CQuorumBlockProcessor& quorum_block_processor, const llmq::CQuorumManager& qman, - std::string& errorRet, bool extended = false); +bool BuildSimplifiedMNListDiff(CDeterministicMNManager& dmnman, const ChainstateManager& chainman, const llmq::CQuorumBlockProcessor& qblockman, + const llmq::CQuorumManager& qman, const uint256& baseBlockHash, const uint256& blockHash, + CSimplifiedMNListDiff& mnListDiffRet, std::string& errorRet, bool extended = false); #endif // BITCOIN_EVO_SIMPLIFIEDMNS_H diff --git a/src/evo/specialtxman.cpp b/src/evo/specialtxman.cpp index 3c4739d6efcf1..3bee881d5e647 100644 --- a/src/evo/specialtxman.cpp +++ b/src/evo/specialtxman.cpp @@ -17,9 +17,11 @@ #include #include #include +#include -static bool CheckSpecialTxInner(CDeterministicMNManager& dmnman, const llmq::CQuorumManager& qman, const CTransaction& tx, const CBlockIndex* pindexPrev, - const CCoinsViewCache& view, const std::optional& indexes, bool check_sigs, TxValidationState& state) +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) { AssertLockHeld(cs_main); @@ -44,17 +46,17 @@ static bool CheckSpecialTxInner(CDeterministicMNManager& dmnman, const llmq::CQu case TRANSACTION_COINBASE: return CheckCbTx(tx, pindexPrev, state); case TRANSACTION_QUORUM_COMMITMENT: - return llmq::CheckLLMQCommitment(dmnman, tx, pindexPrev, state); + return llmq::CheckLLMQCommitment(dmnman, chainman, tx, pindexPrev, state); case TRANSACTION_MNHF_SIGNAL: if (!DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_V20)) { return state.Invalid(TxValidationResult::TX_CONSENSUS, "mnhf-before-v20"); } - return CheckMNHFTx(qman, tx, pindexPrev, state); + return CheckMNHFTx(chainman, qman, tx, pindexPrev, state); case TRANSACTION_ASSET_LOCK: if (!DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_V20)) { return state.Invalid(TxValidationResult::TX_CONSENSUS, "assetlocks-before-v20"); } - return CheckAssetLockUnlockTx(qman, tx, pindexPrev, indexes, state); + return CheckAssetLockUnlockTx(chainman.m_blockman, qman, tx, pindexPrev, indexes, state); case TRANSACTION_ASSET_UNLOCK: if (Params().NetworkIDString() == CBaseChainParams::REGTEST && !DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_V20)) { // TODO: adjust functional tests to make it activated by MN_RR on regtest too @@ -63,7 +65,7 @@ static bool CheckSpecialTxInner(CDeterministicMNManager& dmnman, const llmq::CQu if (Params().NetworkIDString() != CBaseChainParams::REGTEST && !DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_MN_RR)) { return state.Invalid(TxValidationResult::TX_CONSENSUS, "assetunlocks-before-mn_rr"); } - return CheckAssetLockUnlockTx(qman, tx, pindexPrev, indexes, state); + return CheckAssetLockUnlockTx(chainman.m_blockman, qman, tx, pindexPrev, indexes, state); } } catch (const std::exception& e) { LogPrintf("%s -- failed: %s\n", __func__, e.what()); @@ -76,7 +78,7 @@ static bool CheckSpecialTxInner(CDeterministicMNManager& dmnman, const llmq::CQu 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_qman, tx, pindexPrev, view, std::nullopt, check_sigs, state); + return CheckSpecialTxInner(m_dmnman, m_chainman, m_qman, tx, pindexPrev, view, std::nullopt, check_sigs, state); } [[nodiscard]] bool CSpecialTxProcessor::ProcessSpecialTx(const CTransaction& tx, const CBlockIndex* pindex, TxValidationState& state) @@ -155,7 +157,7 @@ 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_qman, *ptr_tx, pindex->pprev, view, creditPool.indexes, fCheckCbTxMerkleRoots, tx_state)) { + if (!CheckSpecialTxInner(m_dmnman, 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())); @@ -273,10 +275,12 @@ bool CSpecialTxProcessor::UndoSpecialTxsInBlock(const CBlock& block, const CBloc bool CSpecialTxProcessor::CheckCreditPoolDiffForBlock(const CBlock& block, const CBlockIndex* pindex, const CAmount blockSubsidy, BlockValidationState& state) { + AssertLockHeld(cs_main); + try { if (!DeploymentActiveAt(*pindex, m_consensus_params, Consensus::DEPLOYMENT_V20)) return true; - auto creditPoolDiff = GetCreditPoolDiffForBlock(m_cpoolman, m_qman, block, pindex->pprev, m_consensus_params, blockSubsidy, state); + auto creditPoolDiff = GetCreditPoolDiffForBlock(m_cpoolman, m_chainman.m_blockman, m_qman, block, pindex->pprev, m_consensus_params, blockSubsidy, state); if (!creditPoolDiff.has_value()) return false; // If we get there we have v20 activated and credit pool amount must be included in block CbTx diff --git a/src/evo/specialtxman.h b/src/evo/specialtxman.h index cddc978961291..537abda90bf1b 100644 --- a/src/evo/specialtxman.h +++ b/src/evo/specialtxman.h @@ -17,6 +17,7 @@ class CBlockIndex; class CCoinsViewCache; class CCreditPoolManager; class CDeterministicMNManager; +class ChainstateManager; class CMNHFManager; class TxValidationState; struct MNListUpdates; @@ -37,6 +38,7 @@ class CSpecialTxProcessor CDeterministicMNManager& m_dmnman; CMNHFManager& m_mnhfman; llmq::CQuorumBlockProcessor& m_qblockman; + const ChainstateManager& m_chainman; const Consensus::Params& m_consensus_params; const llmq::CChainLocksHandler& m_clhandler; const llmq::CQuorumManager& m_qman; @@ -46,10 +48,11 @@ class CSpecialTxProcessor [[nodiscard]] bool UndoSpecialTx(const CTransaction& tx, const CBlockIndex* pindex); public: - explicit CSpecialTxProcessor(CCreditPoolManager& cpoolman, CDeterministicMNManager& dmnman, CMNHFManager& mnhfman, llmq::CQuorumBlockProcessor& qblockman, - 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_consensus_params{consensus_params}, m_clhandler{clhandler}, - m_qman{qman} {} + explicit CSpecialTxProcessor(CCreditPoolManager& cpoolman, CDeterministicMNManager& dmnman, CMNHFManager& mnhfman, + llmq::CQuorumBlockProcessor& qblockman, 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} {} bool CheckSpecialTx(const CTransaction& tx, const CBlockIndex* pindexPrev, const CCoinsViewCache& view, bool check_sigs, TxValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(cs_main); @@ -58,7 +61,8 @@ class CSpecialTxProcessor EXCLUSIVE_LOCKS_REQUIRED(cs_main); bool UndoSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex, std::optional& updatesRet) EXCLUSIVE_LOCKS_REQUIRED(cs_main); - bool CheckCreditPoolDiffForBlock(const CBlock& block, const CBlockIndex* pindex, const CAmount blockSubsidy, BlockValidationState& state); + bool CheckCreditPoolDiffForBlock(const CBlock& block, const CBlockIndex* pindex, const CAmount blockSubsidy, BlockValidationState& state) + EXCLUSIVE_LOCKS_REQUIRED(cs_main); }; #endif // BITCOIN_EVO_SPECIALTXMAN_H diff --git a/src/governance/classes.cpp b/src/governance/classes.cpp index 4c132f065a035..163abde1b6b5d 100644 --- a/src/governance/classes.cpp +++ b/src/governance/classes.cpp @@ -362,14 +362,14 @@ bool CSuperblockManager::GetSuperblockPayments(CGovernanceManager& govman, const return true; } -bool CSuperblockManager::IsValid(CGovernanceManager& govman, const CDeterministicMNList& tip_mn_list, const CTransaction& txNew, int nBlockHeight, CAmount blockReward) +bool CSuperblockManager::IsValid(CGovernanceManager& govman, const CChain& active_chain, const CDeterministicMNList& tip_mn_list, const CTransaction& txNew, int nBlockHeight, CAmount blockReward) { // GET BEST SUPERBLOCK, SHOULD MATCH LOCK(govman.cs); CSuperblock_sptr pSuperblock; if (CSuperblockManager::GetBestSuperblock(govman, tip_mn_list, pSuperblock, nBlockHeight)) { - return pSuperblock->IsValid(govman, txNew, nBlockHeight, blockReward); + return pSuperblock->IsValid(govman, active_chain, txNew, nBlockHeight, blockReward); } return false; @@ -482,7 +482,7 @@ void CSuperblock::GetNearestSuperblocksHeights(int nBlockHeight, int& nLastSuper } } -CAmount CSuperblock::GetPaymentsLimit(int nBlockHeight) +CAmount CSuperblock::GetPaymentsLimit(const CChain& active_chain, int nBlockHeight) { const Consensus::Params& consensusParams = Params().GetConsensus(); @@ -490,7 +490,7 @@ CAmount CSuperblock::GetPaymentsLimit(int nBlockHeight) return 0; } - const CBlockIndex* pindex = ::ChainActive().Tip(); + const CBlockIndex* pindex = active_chain.Tip(); if (pindex->nHeight > nBlockHeight) pindex = pindex->GetAncestor(nBlockHeight); const auto v20_state = g_versionbitscache.State(pindex, consensusParams, Consensus::DEPLOYMENT_V20); @@ -612,7 +612,7 @@ CAmount CSuperblock::GetPaymentsTotalAmount() * - Does this transaction match the superblock? */ -bool CSuperblock::IsValid(CGovernanceManager& govman, const CTransaction& txNew, int nBlockHeight, CAmount blockReward) +bool CSuperblock::IsValid(CGovernanceManager& govman, const CChain& active_chain, const CTransaction& txNew, int nBlockHeight, CAmount blockReward) { // TODO : LOCK(cs); // No reason for a lock here now since this method only accesses data @@ -646,7 +646,7 @@ bool CSuperblock::IsValid(CGovernanceManager& govman, const CTransaction& txNew, // payments should not exceed limit CAmount nPaymentsTotalAmount = GetPaymentsTotalAmount(); - CAmount nPaymentsLimit = GetPaymentsLimit(nBlockHeight); + CAmount nPaymentsLimit = GetPaymentsLimit(active_chain, nBlockHeight); if (nPaymentsTotalAmount > nPaymentsLimit) { LogPrintf("CSuperblock::IsValid -- ERROR: Block invalid, payments limit exceeded: payments %lld, limit %lld\n", nPaymentsTotalAmount, nPaymentsLimit); return false; diff --git a/src/governance/classes.h b/src/governance/classes.h index da85d98dc245b..7ff8eff2e4f8b 100644 --- a/src/governance/classes.h +++ b/src/governance/classes.h @@ -10,12 +10,12 @@ #include