diff --git a/src/dsnotificationinterface.cpp b/src/dsnotificationinterface.cpp index 9bfeb3f82d..a974cccf20 100644 --- a/src/dsnotificationinterface.cpp +++ b/src/dsnotificationinterface.cpp @@ -118,7 +118,7 @@ void CDSNotificationInterface::BlockDisconnected(const std::shared_ptr& pblock, const CBlockIndex* pindex) override; void BlockDisconnected(const std::shared_ptr& pblock, const CBlockIndex* pindexDisconnected) override; - void NotifyMasternodeListChanged(bool undo, const CDeterministicMNList& oldMNList, const CDeterministicMNListDiff& diff, CConnman& connman) override; + void NotifyMasternodeListChanged(bool undo, const CDeterministicMNList& oldMNList, const CDeterministicMNListDiff& diff) override; void NotifyChainLock(const CBlockIndex* pindex, const std::shared_ptr& clsig) override; private: diff --git a/src/evo/deterministicmns.cpp b/src/evo/deterministicmns.cpp index 08696c4ddd..2a0bc7c9ef 100644 --- a/src/evo/deterministicmns.cpp +++ b/src/evo/deterministicmns.cpp @@ -594,7 +594,7 @@ 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) +bool CDeterministicMNManager::ProcessBlock(const CBlock& block, gsl::not_null pindex, BlockValidationState& state, const CCoinsViewCache& view, bool fJustCheck, std::optional& updatesRet) { AssertLockHeld(cs_main); @@ -641,10 +641,8 @@ bool CDeterministicMNManager::ProcessBlock(const CBlock& block, gsl::not_null pindex) +bool CDeterministicMNManager::UndoBlock(gsl::not_null pindex, std::optional& updatesRet) { int nHeight = pindex->nHeight; uint256 blockHash = pindex->GetBlockHash(); @@ -684,8 +682,7 @@ bool CDeterministicMNManager::UndoBlock(gsl::not_null pindex if (diff.HasChanges()) { auto inversedDiff = curList.BuildDiff(prevList); - GetMainSignals().NotifyMasternodeListChanged(true, curList, inversedDiff, connman); - uiInterface.NotifyMasternodeListChanged(prevList, pindex->pprev); + updatesRet = {curList, prevList, inversedDiff}; } const auto& consensusParams = Params().GetConsensus(); diff --git a/src/evo/deterministicmns.h b/src/evo/deterministicmns.h index 69044f5f8d..96e9e5ef42 100644 --- a/src/evo/deterministicmns.h +++ b/src/evo/deterministicmns.h @@ -565,6 +565,13 @@ constexpr int llmq_max_blocks() { return max_blocks; } +struct MNListUpdates +{ + CDeterministicMNList old_list; + CDeterministicMNList new_list; + CDeterministicMNListDiff diff; +}; + class CDeterministicMNManager { static constexpr int DISK_SNAPSHOT_PERIOD = 576; // once per day @@ -596,8 +603,8 @@ public: ~CDeterministicMNManager() = default; bool ProcessBlock(const CBlock& block, gsl::not_null pindex, BlockValidationState& state, - const CCoinsViewCache& view, bool fJustCheck) EXCLUSIVE_LOCKS_REQUIRED(cs_main) LOCKS_EXCLUDED(cs); - bool UndoBlock(gsl::not_null pindex) LOCKS_EXCLUDED(cs); + const CCoinsViewCache& view, bool fJustCheck, std::optional& updatesRet) EXCLUSIVE_LOCKS_REQUIRED(cs_main) LOCKS_EXCLUDED(cs); + bool UndoBlock(gsl::not_null pindex, std::optional& updatesRet) LOCKS_EXCLUDED(cs); void UpdatedBlockTip(gsl::not_null pindex) LOCKS_EXCLUDED(cs); diff --git a/src/evo/specialtxman.cpp b/src/evo/specialtxman.cpp index f4f7ba4dea..0108cc131b 100644 --- a/src/evo/specialtxman.cpp +++ b/src/evo/specialtxman.cpp @@ -133,7 +133,7 @@ static bool UndoSpecialTx(const CTransaction& tx, const CBlockIndex* pindex) bool ProcessSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex, CMNHFManager& mnhfManager, llmq::CQuorumBlockProcessor& quorum_block_processor, const llmq::CChainLocksHandler& chainlock_handler, const Consensus::Params& consensusParams, const CCoinsViewCache& view, bool fJustCheck, bool fCheckCbTxMerleRoots, - BlockValidationState& state) + BlockValidationState& state, std::optional& updatesRet) { AssertLockHeld(cs_main); @@ -181,7 +181,7 @@ bool ProcessSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex, CM nTimeQuorum += nTime3 - nTime2; LogPrint(BCLog::BENCHMARK, " - quorumBlockProcessor: %.2fms [%.2fs]\n", 0.001 * (nTime3 - nTime2), nTimeQuorum * 0.000001); - if (!deterministicMNManager->ProcessBlock(block, pindex, state, view, fJustCheck)) { + if (!deterministicMNManager->ProcessBlock(block, pindex, state, view, fJustCheck, updatesRet)) { // pass the state returned by the function above return false; } @@ -231,7 +231,7 @@ bool ProcessSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex, CM return true; } -bool UndoSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex, CMNHFManager& mnhfManager, llmq::CQuorumBlockProcessor& quorum_block_processor) +bool UndoSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex, CMNHFManager& mnhfManager, llmq::CQuorumBlockProcessor& quorum_block_processor, std::optional& updatesRet) { AssertLockHeld(cs_main); @@ -256,7 +256,7 @@ bool UndoSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex, CMNHF return false; } - if (!deterministicMNManager->UndoBlock(pindex)) { + if (!deterministicMNManager->UndoBlock(pindex, updatesRet)) { return false; } diff --git a/src/evo/specialtxman.h b/src/evo/specialtxman.h index eef77c686e..18a20381dc 100644 --- a/src/evo/specialtxman.h +++ b/src/evo/specialtxman.h @@ -9,12 +9,15 @@ #include #include +#include + class BlockValidationState; class CBlock; class CBlockIndex; class CCoinsViewCache; class CMNHFManager; class TxValidationState; +struct MNListUpdates; namespace llmq { class CQuorumBlockProcessor; class CChainLocksHandler; @@ -30,9 +33,9 @@ bool CheckSpecialTx(const CTransaction& tx, const CBlockIndex* pindexPrev, const bool ProcessSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex, CMNHFManager& mnhfManager, llmq::CQuorumBlockProcessor& quorum_block_processor, const llmq::CChainLocksHandler& chainlock_handler, const Consensus::Params& consensusParams, const CCoinsViewCache& view, bool fJustCheck, bool fCheckCbTxMerleRoots, - BlockValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(cs_main); + BlockValidationState& state, std::optional& updatesRet) EXCLUSIVE_LOCKS_REQUIRED(cs_main); bool UndoSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex, CMNHFManager& mnhfManager, - llmq::CQuorumBlockProcessor& quorum_block_processor) EXCLUSIVE_LOCKS_REQUIRED(cs_main); + llmq::CQuorumBlockProcessor& quorum_block_processor, std::optional& updatesRet) EXCLUSIVE_LOCKS_REQUIRED(cs_main); bool CheckCreditPoolDiffForBlock(const CBlock& block, const CBlockIndex* pindex, const Consensus::Params& consensusParams, const CAmount blockSubsidy, BlockValidationState& state); diff --git a/src/validation.cpp b/src/validation.cpp index b6c8843cdf..cd89ee410d 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -52,6 +52,7 @@ #include #include +#include #include #include #include @@ -1731,7 +1732,8 @@ DisconnectResult CChainState::DisconnectBlock(const CBlock& block, const CBlockI std::vector > addressUnspentIndex; std::vector > spentIndex; - if (!UndoSpecialTxsInBlock(block, pindex, m_mnhfManager, *m_quorum_block_processor)) { + std::optional mnlist_updates_opt{std::nullopt}; + if (!UndoSpecialTxsInBlock(block, pindex, m_mnhfManager, *m_quorum_block_processor, mnlist_updates_opt)) { error("DisconnectBlock(): UndoSpecialTxsInBlock failed"); return DISCONNECT_FAILED; } @@ -1847,6 +1849,12 @@ DisconnectResult CChainState::DisconnectBlock(const CBlock& block, const CBlockI view.SetBestBlock(pindex->pprev->GetBlockHash()); m_evoDb.WriteBestBlock(pindex->pprev->GetBlockHash()); + if (mnlist_updates_opt.has_value()) { + auto mnlu = mnlist_updates_opt.value(); + GetMainSignals().NotifyMasternodeListChanged(true, mnlu.old_list, mnlu.diff); + uiInterface.NotifyMasternodeListChanged(mnlu.new_list, pindex->pprev); + } + auto finish = Now(); auto diff = finish - start; statsClient.timing("DisconnectBlock_ms", count_milliseconds(diff), 1.0f); @@ -2210,7 +2218,8 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state, bool fDIP0001Active_context = pindex->nHeight >= Params().GetConsensus().DIP0001Height; // MUST process special txes before updating UTXO to ensure consistency between mempool and block processing - if (!ProcessSpecialTxsInBlock(block, pindex, m_mnhfManager, *m_quorum_block_processor, *m_clhandler, m_params.GetConsensus(), view, fJustCheck, fScriptChecks, state)) { + std::optional mnlist_updates_opt{std::nullopt}; + if (!ProcessSpecialTxsInBlock(block, pindex, m_mnhfManager, *m_quorum_block_processor, *m_clhandler, m_params.GetConsensus(), view, fJustCheck, fScriptChecks, state, mnlist_updates_opt)) { return error("ConnectBlock(DASH): ProcessSpecialTxsInBlock for block %s failed with %s", pindex->GetBlockHash().ToString(), state.ToString()); } @@ -2470,6 +2479,12 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state, view.SetBestBlock(pindex->GetBlockHash()); m_evoDb.WriteBestBlock(pindex->GetBlockHash()); + if (mnlist_updates_opt.has_value()) { + auto mnlu = mnlist_updates_opt.value(); + GetMainSignals().NotifyMasternodeListChanged(false, mnlu.old_list, mnlu.diff); + uiInterface.NotifyMasternodeListChanged(mnlu.new_list, pindex); + } + int64_t nTime8 = GetTimeMicros(); nTimeCallbacks += nTime8 - nTime5; LogPrint(BCLog::BENCHMARK, " - Callbacks: %.2fms [%.2fs (%.2fms/blk)]\n", MILLI * (nTime8 - nTime5), nTimeCallbacks * MICRO, nTimeCallbacks * MILLI / nBlocksTotal); @@ -4838,7 +4853,8 @@ bool CChainState::RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& i // MUST process special txes before updating UTXO to ensure consistency between mempool and block processing BlockValidationState state; - if (!ProcessSpecialTxsInBlock(block, pindex, m_mnhfManager, *m_quorum_block_processor, *m_clhandler, m_params.GetConsensus(), inputs, false /*fJustCheck*/, false /*fScriptChecks*/, state)) { + std::optional mnlist_updates_opt{std::nullopt}; + if (!ProcessSpecialTxsInBlock(block, pindex, m_mnhfManager, *m_quorum_block_processor, *m_clhandler, m_params.GetConsensus(), inputs, false /*fJustCheck*/, false /*fScriptChecks*/, state, mnlist_updates_opt)) { return error("RollforwardBlock(DASH): ProcessSpecialTxsInBlock for block %s failed with %s", pindex->GetBlockHash().ToString(), state.ToString()); } diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index 19085d8322..1dc40f3aad 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -310,7 +310,7 @@ void CMainSignals::NotifyRecoveredSig(const std::shared_ptrGetHash().ToString()); } -void CMainSignals::NotifyMasternodeListChanged(bool undo, const CDeterministicMNList& oldMNList, const CDeterministicMNListDiff& diff, CConnman& connman) { +void CMainSignals::NotifyMasternodeListChanged(bool undo, const CDeterministicMNList& oldMNList, const CDeterministicMNListDiff& diff) { LOG_EVENT("%s: notify mn list changed undo=%d", __func__, undo); - m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.NotifyMasternodeListChanged(undo, oldMNList, diff, connman); }); + m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.NotifyMasternodeListChanged(undo, oldMNList, diff); }); } diff --git a/src/validationinterface.h b/src/validationinterface.h index 4a29c8c088..018d858ef2 100644 --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -165,7 +165,7 @@ protected: virtual void NotifyGovernanceObject(const std::shared_ptr& object) {} virtual void NotifyInstantSendDoubleSpendAttempt(const CTransactionRef& currentTx, const CTransactionRef& previousTx) {} virtual void NotifyRecoveredSig(const std::shared_ptr& sig) {} - virtual void NotifyMasternodeListChanged(bool undo, const CDeterministicMNList& oldMNList, const CDeterministicMNListDiff& diff, CConnman& connman) {} + virtual void NotifyMasternodeListChanged(bool undo, const CDeterministicMNList& oldMNList, const CDeterministicMNListDiff& diff) {} /** * Notifies listeners of the new active block chain on-disk. * @@ -232,7 +232,7 @@ public: void NotifyGovernanceObject(const std::shared_ptr& object); void NotifyInstantSendDoubleSpendAttempt(const CTransactionRef ¤tTx, const CTransactionRef &previousTx); void NotifyRecoveredSig(const std::shared_ptr &sig); - void NotifyMasternodeListChanged(bool undo, const CDeterministicMNList& oldMNList, const CDeterministicMNListDiff& diff, CConnman& connman); + void NotifyMasternodeListChanged(bool undo, const CDeterministicMNList& oldMNList, const CDeterministicMNListDiff& diff); void ChainStateFlushed(const CBlockLocator &); void BlockChecked(const CBlock&, const BlockValidationState&); void NewPoWValidBlock(const CBlockIndex *, const std::shared_ptr&); diff --git a/test/lint/lint-circular-dependencies.sh b/test/lint/lint-circular-dependencies.sh index ed25df4f21..2486083977 100755 --- a/test/lint/lint-circular-dependencies.sh +++ b/test/lint/lint-circular-dependencies.sh @@ -105,6 +105,7 @@ EXPECTED_CIRCULAR_DEPENDENCIES=( "llmq/debug -> llmq/dkgsessionhandler -> llmq/dkgsession -> llmq/debug" "llmq/utils -> validation -> llmq/utils" "evo/mnhftx -> validation -> evo/mnhftx" + "evo/deterministicmns -> validation -> evo/deterministicmns" ) EXIT_CODE=0