Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions doc/release-notes-7062.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# RPC changes

- `quorum dkginfo` will now require that nodes run either in watch-only mode (`-watchquorums`) or as an
active masternode (i.e. masternode mode) as regular nodes do not have insight into network DKG activity.

- `quorum dkgstatus` will no longer emit the return values `time`, `timeStr` and `session` on nodes that
do not run in either watch-only or masternode mode as regular nodes do not have insight into network
DKG activity.
5 changes: 2 additions & 3 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2225,9 +2225,8 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
g_active_notification_interface = std::make_unique<ActiveNotificationInterface>(*node.active_ctx, *node.mn_activeman);
RegisterValidationInterface(g_active_notification_interface.get());
} else if (quorums_watch) {
node.observer_ctx = std::make_unique<llmq::ObserverContext>(*node.llmq_ctx->bls_worker, *node.dmnman, *node.mn_metaman, *node.llmq_ctx->dkg_debugman,
*node.llmq_ctx->quorum_block_processor, *node.llmq_ctx->qman, *node.llmq_ctx->qsnapman, chainman,
*node.sporkman, dash_db_params);
node.observer_ctx = std::make_unique<llmq::ObserverContext>(*node.llmq_ctx->bls_worker, *node.dmnman, *node.mn_metaman, *node.llmq_ctx->quorum_block_processor,
*node.llmq_ctx->qman, *node.llmq_ctx->qsnapman, chainman, *node.sporkman, dash_db_params);
RegisterValidationInterface(node.observer_ctx.get());
}

Expand Down
2 changes: 0 additions & 2 deletions src/llmq/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
#include <chainlock/chainlock.h>
#include <instantsend/instantsend.h>
#include <llmq/blockprocessor.h>
#include <llmq/debug.h>
#include <llmq/quorums.h>
#include <llmq/signing.h>
#include <llmq/snapshot.h>
Expand All @@ -20,7 +19,6 @@ LLMQContext::LLMQContext(ChainstateManager& chainman, CDeterministicMNManager& d
const llmq::QvvecSyncModeMap& sync_map, const util::DbWrapperParams& db_params,
bool quorums_recovery, bool quorums_watch, int8_t bls_threads, int64_t max_recsigs_age) :
bls_worker{std::make_shared<CBLSWorker>()},
dkg_debugman{std::make_unique<llmq::CDKGDebugManager>()},
qsnapman{std::make_unique<llmq::CQuorumSnapshotManager>(evo_db)},
quorum_block_processor{std::make_unique<llmq::CQuorumBlockProcessor>(chainman.ActiveChainstate(), dmnman, evo_db,
*qsnapman, bls_threads)},
Expand Down
2 changes: 0 additions & 2 deletions src/llmq/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ class PeerManager;

namespace llmq {
class CChainLocksHandler;
class CDKGDebugManager;
class CInstantSendManager;
class CQuorumBlockProcessor;
class CQuorumManager;
Expand Down Expand Up @@ -58,7 +57,6 @@ struct LLMQContext {
* but it still guarantees that objects are created and valid
*/
const std::shared_ptr<CBLSWorker> bls_worker;
const std::unique_ptr<llmq::CDKGDebugManager> dkg_debugman;
const std::unique_ptr<llmq::CQuorumSnapshotManager> qsnapman;
const std::unique_ptr<llmq::CQuorumBlockProcessor> quorum_block_processor;
const std::unique_ptr<llmq::CQuorumManager> qman;
Expand Down
8 changes: 4 additions & 4 deletions src/llmq/core_write.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,13 @@ RPCResult CDKGDebugSessionStatus::GetJsonHelp(const std::string& key, bool optio
}

// CDKGDebugStatus::ToJson() defined in llmq/debug.cpp
RPCResult CDKGDebugStatus::GetJsonHelp(const std::string& key, bool optional)
RPCResult CDKGDebugStatus::GetJsonHelp(const std::string& key, bool optional, bool inner_optional)
{
return {RPCResult::Type::OBJ, key, optional, key.empty() ? "" : "The state of the node's DKG sessions",
{
{RPCResult::Type::NUM, "time", "Adjusted time for the last update, timestamp"},
{RPCResult::Type::STR, "timeStr", "Adjusted time for the last update, human friendly"},
{RPCResult::Type::ARR, "session", "", {
{RPCResult::Type::NUM, "time", inner_optional, "Adjusted time for the last update, timestamp"},
{RPCResult::Type::STR, "timeStr", inner_optional, "Adjusted time for the last update, human friendly"},
{RPCResult::Type::ARR, "session", inner_optional, "", {
{RPCResult::Type::OBJ, "", "", {
{RPCResult::Type::NUM, "llmqType", "Name of quorum"},
GetRpcResult("quorumIndex"),
Expand Down
2 changes: 1 addition & 1 deletion src/llmq/debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ class CDKGDebugStatus
//std::map<Consensus::LLMQType, CDKGDebugSessionStatus> sessions;

public:
[[nodiscard]] static RPCResult GetJsonHelp(const std::string& key, bool optional);
[[nodiscard]] static RPCResult GetJsonHelp(const std::string& key, bool optional, bool inner_optional = false);
[[nodiscard]] UniValue ToJson(CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman,
const ChainstateManager& chainman, int detailLevel) const;
};
Expand Down
11 changes: 6 additions & 5 deletions src/llmq/observer/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,20 @@

#include <llmq/observer/context.h>

#include <llmq/debug.h>
#include <llmq/dkgsessionmgr.h>
#include <llmq/quorums.h>

namespace llmq {
ObserverContext::ObserverContext(CBLSWorker& bls_worker, CDeterministicMNManager& dmnman,
CMasternodeMetaMan& mn_metaman, llmq::CDKGDebugManager& dkg_debugman,
ObserverContext::ObserverContext(CBLSWorker& bls_worker, CDeterministicMNManager& dmnman, CMasternodeMetaMan& mn_metaman,
llmq::CQuorumBlockProcessor& qblockman, llmq::CQuorumManager& qman,
llmq::CQuorumSnapshotManager& qsnapman, const ChainstateManager& chainman,
const CSporkManager& sporkman, const util::DbWrapperParams& db_params) :
m_qman{qman},
qdkgsman{std::make_unique<llmq::CDKGSessionManager>(bls_worker, dmnman, dkg_debugman, mn_metaman, qblockman,
qsnapman, /*mn_activeman=*/nullptr, chainman, sporkman,
db_params, /*quorums_watch=*/true)}
dkgdbgman{std::make_unique<llmq::CDKGDebugManager>()},
qdkgsman{std::make_unique<llmq::CDKGSessionManager>(bls_worker, dmnman, *dkgdbgman, mn_metaman, qblockman, qsnapman,
/*mn_activeman=*/nullptr, chainman, sporkman, db_params,
/*quorums_watch=*/true)}
{
m_qman.ConnectManager(qdkgsman.get());
}
Expand Down
5 changes: 3 additions & 2 deletions src/llmq/observer/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ struct ObserverContext final : public CValidationInterface {
ObserverContext(const ObserverContext&) = delete;
ObserverContext& operator=(const ObserverContext&) = delete;
ObserverContext(CBLSWorker& bls_worker, CDeterministicMNManager& dmnman, CMasternodeMetaMan& mn_metaman,
llmq::CDKGDebugManager& dkg_debugman, llmq::CQuorumBlockProcessor& qblockman,
llmq::CQuorumManager& qman, llmq::CQuorumSnapshotManager& qsnapman, const ChainstateManager& chainman,
llmq::CQuorumBlockProcessor& qblockman, llmq::CQuorumManager& qman,
llmq::CQuorumSnapshotManager& qsnapman, const ChainstateManager& chainman,
const CSporkManager& sporkman, const util::DbWrapperParams& db_params);
~ObserverContext();

Expand All @@ -46,6 +46,7 @@ struct ObserverContext final : public CValidationInterface {
void UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork, bool fInitialDownload) override;

public:
const std::unique_ptr<llmq::CDKGDebugManager> dkgdbgman;
const std::unique_ptr<llmq::CDKGSessionManager> qdkgsman;
};
} // namespace llmq
Expand Down
6 changes: 4 additions & 2 deletions src/masternode/active/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <instantsend/instantsend.h>
#include <instantsend/signing.h>
#include <llmq/context.h>
#include <llmq/debug.h>
#include <llmq/dkgsessionmgr.h>
#include <llmq/ehf_signals.h>
#include <llmq/quorums.h>
Expand All @@ -25,8 +26,9 @@ ActiveContext::ActiveContext(CCoinJoinServer& cj_server, CConnman& connman, CDet
m_llmq_ctx{llmq_ctx},
m_cj_server(cj_server),
gov_signer{std::make_unique<GovernanceSigner>(connman, dmnman, govman, mn_activeman, chainman, mn_sync)},
qdkgsman{std::make_unique<llmq::CDKGSessionManager>(*llmq_ctx.bls_worker, dmnman, *llmq_ctx.dkg_debugman,
mn_metaman, *llmq_ctx.quorum_block_processor, *llmq_ctx.qsnapman,
dkgdbgman{std::make_unique<llmq::CDKGDebugManager>()},
qdkgsman{std::make_unique<llmq::CDKGSessionManager>(*llmq_ctx.bls_worker, dmnman, *dkgdbgman, mn_metaman,
*llmq_ctx.quorum_block_processor, *llmq_ctx.qsnapman,
&mn_activeman, chainman, sporkman, db_params, quorums_watch)},
shareman{std::make_unique<llmq::CSigSharesManager>(connman, chainman.ActiveChainstate(), *llmq_ctx.sigman, peerman,
mn_activeman, *llmq_ctx.qman, sporkman)},
Expand Down
2 changes: 2 additions & 0 deletions src/masternode/active/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ namespace instantsend {
class InstantSendSigner;
} // namespace instantsend
namespace llmq {
class CDKGDebugManager;
class CDKGSessionManager;
class CEHFSignalsHandler;
class CSigSharesManager;
Expand Down Expand Up @@ -63,6 +64,7 @@ struct ActiveContext {
*/
CCoinJoinServer& m_cj_server;
const std::unique_ptr<GovernanceSigner> gov_signer;
const std::unique_ptr<llmq::CDKGDebugManager> dkgdbgman;
const std::unique_ptr<llmq::CDKGSessionManager> qdkgsman;
const std::unique_ptr<llmq::CSigSharesManager> shareman;
const std::unique_ptr<llmq::CEHFSignalsHandler> ehf_sighandler;
Expand Down
51 changes: 28 additions & 23 deletions src/rpc/quorums.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <llmq/context.h>
#include <llmq/debug.h>
#include <llmq/dkgsession.h>
#include <llmq/observer/context.h>
#include <llmq/options.h>
#include <llmq/quorums.h>
#include <llmq/signhash.h>
Expand Down Expand Up @@ -296,7 +297,7 @@ static RPCHelpMan quorum_info()

static RPCResult quorum_dkgstatus_help()
{
auto ret = llmq::CDKGDebugStatus::GetJsonHelp(/*key=*/"", /*optional=*/false);
auto ret = llmq::CDKGDebugStatus::GetJsonHelp(/*key=*/"", /*optional=*/false, /*inner_optional=*/true);
auto mod_inner = ret.m_inner;
mod_inner.push_back({RPCResult::Type::ARR, "quorumConnections", "Array of objects containing quorum connection information", {
{RPCResult::Type::OBJ, "", "", {
Expand Down Expand Up @@ -332,12 +333,6 @@ static RPCHelpMan quorum_dkgstatus()
RPCExamples{""},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
const NodeContext& node = EnsureAnyNodeContext(request.context);
const ChainstateManager& chainman = EnsureChainman(node);
const LLMQContext& llmq_ctx = EnsureLLMQContext(node);
const CConnman& connman = EnsureConnman(node);
CHECK_NONFATAL(node.sporkman);

int detailLevel = 0;
if (!request.params[0].isNull()) {
detailLevel = ParseInt32V(request.params[0], "detail_level");
Expand All @@ -346,17 +341,25 @@ static RPCHelpMan quorum_dkgstatus()
}
}

llmq::CDKGDebugStatus status;
llmq_ctx.dkg_debugman->GetLocalDebugStatus(status);

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;
const uint256 proTxHash = node.mn_activeman ? node.mn_activeman->GetProTxHash() : uint256();

UniValue ret(UniValue::VOBJ);
UniValue minableCommitments(UniValue::VARR);
UniValue quorumArrConnections(UniValue::VARR);

const NodeContext& node = EnsureAnyNodeContext(request.context);
const ChainstateManager& chainman = EnsureChainman(node);
const LLMQContext& llmq_ctx = EnsureLLMQContext(node);
if (const auto* debugman = node.active_ctx ? node.active_ctx->dkgdbgman.get()
: node.observer_ctx ? node.observer_ctx->dkgdbgman.get()
: nullptr; debugman) {
llmq::CDKGDebugStatus status;
debugman->GetLocalDebugStatus(status);
ret = status.ToJson(*CHECK_NONFATAL(node.dmnman), *llmq_ctx.qsnapman, chainman, detailLevel);
}

const CConnman& connman = EnsureConnman(node);
const CBlockIndex* const pindexTip = WITH_LOCK(cs_main, return chainman.ActiveChain().Tip());
const int tipHeight = pindexTip->nHeight;
const uint256 proTxHash = node.mn_activeman ? node.mn_activeman->GetProTxHash() : uint256{};
for (const auto& type : llmq::GetEnabledQuorumTypes(chainman, pindexTip)) {
const auto llmq_params_opt = Params().GetLLMQ(type);
CHECK_NONFATAL(llmq_params_opt.has_value());
Expand All @@ -377,14 +380,14 @@ static RPCHelpMan quorum_dkgstatus()
obj.pushKV("quorumHash", pQuorumBaseBlockIndex->GetBlockHash().ToString());
obj.pushKV("pindexTip", pindexTip->nHeight);

auto allConnections = llmq::utils::GetQuorumConnections(llmq_params, *node.sporkman,
auto allConnections = llmq::utils::GetQuorumConnections(llmq_params, *CHECK_NONFATAL(node.sporkman),
{*node.dmnman, *llmq_ctx.qsnapman, chainman,
pQuorumBaseBlockIndex},
proTxHash, false);
proTxHash, /*onlyOutbound=*/false);
auto outboundConnections = llmq::utils::GetQuorumConnections(llmq_params, *node.sporkman,
{*node.dmnman, *llmq_ctx.qsnapman,
chainman, pQuorumBaseBlockIndex},
proTxHash, true);
proTxHash, /*onlyOutbound=*/true);
std::map<uint256, CAddress> foundConnections;
connman.ForEachNode([&](const CNode* pnode) {
auto verifiedProRegTxHash = pnode->GetVerifiedProRegTxHash();
Expand Down Expand Up @@ -943,7 +946,6 @@ static RPCHelpMan quorum_rotationinfo()
const NodeContext& node = EnsureAnyNodeContext(request.context);
const ChainstateManager& chainman = EnsureChainman(node);
const LLMQContext& llmq_ctx = EnsureLLMQContext(node);
;

llmq::CGetQuorumRotationInfo cmd;
llmq::CQuorumRotationInfo quorumRotationInfoRet;
Expand Down Expand Up @@ -997,14 +999,17 @@ static RPCHelpMan quorum_dkginfo()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
const NodeContext& node = EnsureAnyNodeContext(request.context);
const ChainstateManager& chainman = EnsureChainman(node);
const LLMQContext& llmq_ctx = EnsureLLMQContext(node);
if (!node.active_ctx && !node.observer_ctx) {
throw JSONRPCError(RPC_INTERNAL_ERROR, "Only available in masternode or watch-only mode.");
}
const auto& dkgdbgman = *(node.active_ctx ? node.active_ctx->dkgdbgman.get() : node.observer_ctx->dkgdbgman.get());

llmq::CDKGDebugStatus status;
llmq_ctx.dkg_debugman->GetLocalDebugStatus(status);
dkgdbgman.GetLocalDebugStatus(status);
UniValue ret(UniValue::VOBJ);
ret.pushKV("active_dkgs", status.sessions.size());

const ChainstateManager& chainman = EnsureChainman(node);
const int nTipHeight{WITH_LOCK(cs_main, return chainman.ActiveChain().Height())};
auto minNextDKG = [](const Consensus::Params& consensusParams, int nTipHeight) {
int minDkgWindow{std::numeric_limits<int>::max()};
Expand Down
10 changes: 4 additions & 6 deletions test/functional/feature_llmq_rotation.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ def run_test(self):

tip = self.nodes[0].getblockcount()
next_dkg = 24 - (tip % 24)
for node in self.nodes:
dkg_info = node.quorum("dkginfo")
for mn in self.mninfo:
dkg_info = mn.get_node(self).quorum("dkginfo")
assert_equal(dkg_info['active_dkgs'], 0)
assert_equal(dkg_info['next_dkg'], next_dkg)

Expand All @@ -94,10 +94,8 @@ def run_test(self):
next_dkg = 24 - (tip % 24)
assert next_dkg < 24
nonzero_dkgs = 0
for i in range(len(self.nodes)):
dkg_info = self.nodes[i].quorum("dkginfo")
if i == 0:
assert_equal(dkg_info['active_dkgs'], 0)
for mn in self.mninfo:
dkg_info = mn.get_node(self).quorum("dkginfo")
nonzero_dkgs += dkg_info['active_dkgs']
assert_equal(dkg_info['next_dkg'], next_dkg)
assert_equal(nonzero_dkgs, 4) # 1 quorums 4 nodes
Expand Down
2 changes: 1 addition & 1 deletion test/functional/feature_llmq_simplepose.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ def mine_quorum_less_checks(self, expected_good_nodes, mninfos_online):
self.wait_for_quorum_phase(q, 6, expected_good_nodes, None, 0, mninfos_online)

self.log.info("Waiting final commitment")
self.wait_for_quorum_commitment(q, nodes)
self.wait_for_quorum_commitment(q, mninfos_online)

self.log.info("Mining final commitment")
self.bump_mocktime(1, nodes=nodes)
Expand Down
8 changes: 4 additions & 4 deletions test/functional/test_framework/test_framework.py
Original file line number Diff line number Diff line change
Expand Up @@ -2065,10 +2065,10 @@ def check_dkg_session():

self.wait_until(check_dkg_session, timeout=timeout, sleep=sleep)

def wait_for_quorum_commitment(self, quorum_hash, nodes, llmq_type=100, timeout=15):
def wait_for_quorum_commitment(self, quorum_hash, mninfos, llmq_type=100, timeout=15):
def check_dkg_comitments():
for node in nodes:
s = node.quorum("dkgstatus")
for mn in mninfos:
s = mn.get_node(self).quorum("dkgstatus")
if "minableCommitments" not in s:
return False
commits = s["minableCommitments"]
Expand Down Expand Up @@ -2169,7 +2169,7 @@ def mine_quorum(self, llmq_type_name="llmq_test", llmq_type=100, expected_connec
self.wait_for_quorum_phase(q, 6, expected_members, None, 0, mninfos_online, llmq_type_name=llmq_type_name)

self.log.info("Waiting final commitment")
self.wait_for_quorum_commitment(q, nodes, llmq_type=llmq_type)
self.wait_for_quorum_commitment(q, mninfos_online, llmq_type=llmq_type)

self.log.info("Mining final commitment")
self.bump_mocktime(1)
Expand Down
Loading