From 9c9cac6d674773fe33a7a3616d305d182113288a Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Wed, 8 Jan 2020 08:01:26 +0100 Subject: [PATCH] Show quorum connections in "quorum dkgstatus" and use it in mine_quorum (#3271) Instead of statically sleeping 2 seconds --- src/rpc/rpcquorums.cpp | 29 +++++++++++++++++++ test/functional/llmq-simplepose.py | 2 +- .../test_framework/test_framework.py | 29 +++++++++++++++++-- 3 files changed, 56 insertions(+), 4 deletions(-) diff --git a/src/rpc/rpcquorums.cpp b/src/rpc/rpcquorums.cpp index 25e46fbb44..bd4fd5cc6c 100644 --- a/src/rpc/rpcquorums.cpp +++ b/src/rpc/rpcquorums.cpp @@ -6,6 +6,8 @@ #include "server.h" #include "validation.h" +#include "masternode/activemasternode.h" + #include "llmq/quorums.h" #include "llmq/quorums_blockprocessor.h" #include "llmq/quorums_debug.h" @@ -176,8 +178,34 @@ UniValue quorum_dkgstatus(const JSONRPCRequest& request) int tipHeight = chainActive.Height(); UniValue minableCommitments(UniValue::VOBJ); + UniValue quorumConnections(UniValue::VOBJ); for (const auto& p : Params().GetConsensus().llmqs) { auto& params = p.second; + + if (fMasternodeMode) { + const CBlockIndex* pindexQuorum = chainActive[tipHeight - (tipHeight % params.dkgInterval)]; + auto expectedConnections = llmq::CLLMQUtils::GetQuorumConnections(params.type, pindexQuorum, activeMasternodeInfo.proTxHash); + std::map foundConnections; + g_connman->ForEachNode([&](const CNode* pnode) { + if (!pnode->verifiedProRegTxHash.IsNull() && expectedConnections.count(pnode->verifiedProRegTxHash)) { + foundConnections.emplace(pnode->verifiedProRegTxHash, pnode->addr); + } + }); + UniValue arr(UniValue::VARR); + for (auto& ec : expectedConnections) { + UniValue obj(UniValue::VOBJ); + obj.push_back(Pair("proTxHash", ec.ToString())); + if (foundConnections.count(ec)) { + obj.push_back(Pair("connected", true)); + obj.push_back(Pair("address", foundConnections[ec].ToString(false))); + } else { + obj.push_back(Pair("connected", false)); + } + arr.push_back(obj); + } + quorumConnections.push_back(Pair(params.name, arr)); + } + llmq::CFinalCommitment fqc; if (llmq::quorumBlockProcessor->GetMinableCommitment(params.type, tipHeight, fqc)) { UniValue obj(UniValue::VOBJ); @@ -187,6 +215,7 @@ UniValue quorum_dkgstatus(const JSONRPCRequest& request) } ret.push_back(Pair("minableCommitments", minableCommitments)); + ret.push_back(Pair("quorumConnections", quorumConnections)); return ret; } diff --git a/test/functional/llmq-simplepose.py b/test/functional/llmq-simplepose.py index 3b84ec525c..6d9c8ea172 100755 --- a/test/functional/llmq-simplepose.py +++ b/test/functional/llmq-simplepose.py @@ -40,7 +40,7 @@ class LLMQSimplePoSeTest(DashTestFramework): t = time.time() while (not self.check_punished(mn) or not self.check_banned(mn)) and (time.time() - t) < 120: - self.mine_quorum(expected_members=i-1, expected_contributions=i-1, expected_complaints=i-1, expected_commitments=i-1) + self.mine_quorum(expected_connections=1, expected_members=i-1, expected_contributions=i-1, expected_complaints=i-1, expected_commitments=i-1) assert(self.check_punished(mn) and self.check_banned(mn)) diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 4acf883899..1f9085e618 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -756,6 +756,30 @@ class DashTestFramework(BitcoinTestFramework): return all(node.spork('show') == sporks for node in self.nodes[1:]) wait_until(check_sporks_same, timeout=timeout, sleep=0.5) + def wait_for_quorum_connections(self, expected_connections=2, timeout = 30): + def check_quorum_connections(): + all_ok = True + for node in self.nodes: + s = node.quorum("dkgstatus") + if s["session"] == {}: + continue + if "quorumConnections" not in s: + all_ok = False + break + s = s["quorumConnections"] + if "llmq_test" not in s: + all_ok = False + break + cnt = 0 + for c in s["llmq_test"]: + if c["connected"]: + cnt += 1 + if cnt < expected_connections: + all_ok = False + break + return all_ok + wait_until(check_quorum_connections, timeout=timeout, sleep=0.1) + def wait_for_quorum_phase(self, phase, expected_member_count, check_received_messages, check_received_messages_count, timeout=30): def check_dkg_session(): all_ok = True @@ -796,7 +820,7 @@ class DashTestFramework(BitcoinTestFramework): return all_ok wait_until(check_dkg_comitments, timeout=timeout, sleep=0.1) - def mine_quorum(self, expected_members=None, expected_contributions=None, expected_complaints=0, expected_justifications=0, expected_commitments=None): + def mine_quorum(self, expected_members=None, expected_connections=2, expected_contributions=None, expected_complaints=0, expected_justifications=0, expected_commitments=None): if expected_members is None: expected_members = self.llmq_size if expected_contributions is None: @@ -820,8 +844,7 @@ class DashTestFramework(BitcoinTestFramework): self.log.info("Waiting for phase 1 (init)") self.wait_for_quorum_phase(1, expected_members, None, 0) - # Give nodes some time to connect to neighbors - time.sleep(2) + self.wait_for_quorum_connections(expected_connections=expected_connections) self.bump_mocktime(1) set_node_times(self.nodes, self.mocktime) self.nodes[0].generate(2)