From e2ed82a7ae8949ab16e3aeb4d9a8d3ccb0d81d4b Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Wed, 25 Sep 2024 13:56:35 +0300 Subject: [PATCH 1/3] feat(rpc): introduce `setmnthreadactive` (regtest-only) --- src/net.cpp | 3 +-- src/net.h | 3 +++ src/rpc/client.cpp | 1 + src/rpc/net.cpp | 27 +++++++++++++++++++++++++++ src/test/fuzz/rpc.cpp | 1 + 5 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index e1c86e2396..a49132c8df 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -3486,8 +3486,7 @@ void CConnman::ThreadOpenMasternodeConnections(CDeterministicMNManager& dmnman, didConnect = false; - if (!fNetworkActive || !mn_sync.IsBlockchainSynced()) - continue; + if (!fNetworkActive || !m_masternode_thread_active || !mn_sync.IsBlockchainSynced()) continue; std::set connectedNodes; std::map connectedProRegTxHashes; diff --git a/src/net.h b/src/net.h index 33c6c8908c..ab17ca7758 100644 --- a/src/net.h +++ b/src/net.h @@ -1223,6 +1223,8 @@ public: bool GetNetworkActive() const { return fNetworkActive; }; bool GetUseAddrmanOutgoing() const { return m_use_addrman_outgoing; }; void SetNetworkActive(bool active, CMasternodeSync* const mn_sync); + bool GetMasternodeThreadActive() const { return m_masternode_thread_active; }; + void SetMasternodeThreadActive(bool active) { m_masternode_thread_active = active; }; SocketEventsMode GetSocketEventsMode() const { return socketEventsMode; } enum class MasternodeConn { @@ -1721,6 +1723,7 @@ private: std::vector vhListenSocket; std::atomic fNetworkActive{true}; + std::atomic m_masternode_thread_active{true}; bool fAddressesInitialized{false}; AddrMan& addrman; const NetGroupManager& m_netgroupman; diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 8af1bcf441..fd4d3a08d4 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -175,6 +175,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "prioritisetransaction", 1, "fee_delta" }, { "setban", 2, "bantime" }, { "setban", 3, "absolute" }, + { "setmnthreadactive", 0, "state" }, { "setnetworkactive", 0, "state" }, { "setcoinjoinrounds", 0, "rounds" }, { "setcoinjoinamount", 0, "amount" }, diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index b4c962fd87..a5ae324644 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -1019,6 +1019,32 @@ static RPCHelpMan addpeeraddress() }; } +static RPCHelpMan setmnthreadactive() +{ + return RPCHelpMan{"setmnthreadactive", + "\nDisable/enable automatic masternode connections thread activity.\n", + { + {"state", RPCArg::Type::BOOL, RPCArg::Optional::NO, "true to enable the thread, false to disable"}, + }, + RPCResult{RPCResult::Type::BOOL, "", "The value that was passed in"}, + RPCExamples{""}, + [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue +{ + + if (Params().NetworkIDString() != CBaseChainParams::REGTEST) { + throw std::runtime_error("setmnthreadactive is for regression testing (-regtest mode) only."); + } + + const NodeContext& node = EnsureAnyNodeContext(request.context); + CConnman& connman = EnsureConnman(node); + + connman.SetMasternodeThreadActive(request.params[0].get_bool()); + + return connman.GetMasternodeThreadActive(); +}, + }; +} + void RegisterNetRPCCommands(CRPCTable &t) { // clang-format off @@ -1042,6 +1068,7 @@ static const CRPCCommand commands[] = { "hidden", &addconnection, }, { "hidden", &addpeeraddress, }, + { "hidden", &setmnthreadactive }, }; // clang-format on for (const auto& c : commands) { diff --git a/src/test/fuzz/rpc.cpp b/src/test/fuzz/rpc.cpp index 79062ef49d..7a2e052649 100644 --- a/src/test/fuzz/rpc.cpp +++ b/src/test/fuzz/rpc.cpp @@ -150,6 +150,7 @@ const std::vector RPC_COMMANDS_SAFE_FOR_FUZZING{ "reconsiderblock", "scantxoutset", "sendrawtransaction", + "setmnthreadactive", "setmocktime", "setnetworkactive", "signmessagewithprivkey", From be72ef5592635c13afdd497f05c15f46e987e550 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Wed, 25 Sep 2024 13:57:08 +0300 Subject: [PATCH 2/3] test: use `setmnthreadactive` to get controlable `connect_nodes` behaviour --- test/functional/test_framework/test_framework.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index ccbc459667..8fd2d52a9b 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -1083,6 +1083,8 @@ class MasternodeInfo: self.collateral_vout = collateral_vout self.addr = addr self.evo = evo + self.node = None + self.nodeIdx = None class DashTestFramework(BitcoinTestFramework): @@ -1097,6 +1099,15 @@ class DashTestFramework(BitcoinTestFramework): """Tests must override this method to define test logic""" raise NotImplementedError + def connect_nodes(self, a, b): + for mn2 in self.mninfo: + if mn2.node is not None: + mn2.node.setmnthreadactive(False) + super().connect_nodes(a, b) + for mn2 in self.mninfo: + if mn2.node is not None: + mn2.node.setmnthreadactive(True) + def set_dash_test_params(self, num_nodes, masterodes_count, extra_args=None, fast_dip3_enforcement=False, evo_count=0): self.mn_count = masterodes_count self.evo_count = evo_count From 1e17b7420785a0f92ce512167c2bce59b08538df Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Wed, 25 Sep 2024 14:29:45 +0300 Subject: [PATCH 3/3] test: no longer connect nodes in parallel in `start_masternodes` --- test/functional/test_framework/test_framework.py | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 8fd2d52a9b..d30ff52bca 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -1446,17 +1446,12 @@ class DashTestFramework(BitcoinTestFramework): job.result() jobs.clear() - # connect nodes in parallel - for idx in range(0, self.mn_count): - jobs.append(executor.submit(do_connect, idx)) - - # wait for all nodes to connect - for job in jobs: - job.result() - jobs.clear() - executor.shutdown() + # connect nodes + for idx in range(0, self.mn_count): + do_connect(idx) + def start_masternode(self, mninfo, extra_args=None): args = ['-masternodeblsprivkey=%s' % mninfo.keyOperator] + self.extra_args[mninfo.nodeIdx] if extra_args is not None: