-
Notifications
You must be signed in to change notification settings - Fork 1.2k
refactor: expose masternode Platform endpoints, quorum keys and islocks via node interface #7591
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -28,6 +28,7 @@ | |
| #include <interfaces/handler.h> | ||
| #include <interfaces/wallet.h> | ||
| #include <instantsend/instantsend.h> | ||
| #include <llmq/blockprocessor.h> | ||
| #include <llmq/commitment.h> | ||
| #include <llmq/context.h> | ||
| #include <llmq/options.h> | ||
|
|
@@ -134,6 +135,27 @@ class MnEntryImpl : public MnEntry | |
| bool isBanned() const override { return m_dmn->pdmnState->IsBanned(); } | ||
|
|
||
| CService getNetInfoPrimary() const override { return m_dmn->pdmnState->netInfo->GetPrimary(); } | ||
| std::vector<CService> getPlatformHTTPSAddrs() const override | ||
| { | ||
| std::vector<CService> ret; | ||
| if (m_dmn->pdmnState->nVersion < ProTxVersion::ExtAddr) { | ||
| // Before ExtAddr the Platform ports are scalar fields paired with | ||
| // the primary address instead of netInfo entries, so an evonode | ||
| // that has not submitted an extended-address update would | ||
| // otherwise contribute no gateway at all. | ||
| if (m_dmn->nType == MnType::Evo && m_dmn->pdmnState->platformHTTPPort != 0) { | ||
| ret.emplace_back(m_dmn->pdmnState->netInfo->GetPrimary(), | ||
| m_dmn->pdmnState->platformHTTPPort); | ||
| } | ||
| return ret; | ||
| } | ||
| for (const auto& entry : m_dmn->pdmnState->netInfo->GetEntries(NetInfoPurpose::PLATFORM_HTTPS)) { | ||
| if (const auto service_opt{entry.GetAddrPort()}) { | ||
| ret.push_back(*service_opt); | ||
| } | ||
| } | ||
| return ret; | ||
| } | ||
| MnType getType() const override { return m_dmn->nType; } | ||
| UniValue toJson() const override { return m_dmn->ToJson(); } | ||
| const CKeyID& getKeyIdOwner() const override { return m_dmn->pdmnState->keyIDOwner; } | ||
|
|
@@ -539,6 +561,58 @@ class LLMQImpl : public LLMQ | |
| } | ||
| return stats; | ||
| } | ||
| std::vector<PlatformQuorum> getPlatformQuorums(uint8_t llmq_type) override | ||
| { | ||
| std::vector<PlatformQuorum> ret; | ||
| if (!context().llmq_ctx || !context().llmq_ctx->quorum_block_processor || !context().chainman) { | ||
| return ret; | ||
| } | ||
| const auto* pindex{WITH_LOCK(::cs_main, return context().chainman->ActiveChain().Tip())}; | ||
| if (!pindex) { | ||
| return ret; | ||
| } | ||
| const auto type{static_cast<Consensus::LLMQType>(llmq_type)}; | ||
| const auto llmq_params{Params().GetLLMQ(type)}; | ||
| if (!llmq_params.has_value()) { | ||
| return ret; | ||
| } | ||
| // Drive proofs may be signed by an older Platform quorum while they | ||
| // are still consensus-valid and retained locally. Export the full | ||
| // retained-key window, not only the current signing-active set. | ||
| const auto quorum_count{static_cast<size_t>(std::max(llmq_params->signingActiveQuorumCount, | ||
| llmq_params->keepOldKeys))}; | ||
| // Read mined final commitments directly: they already carry the quorum | ||
| // hash and public key, so there is no need to materialize full CQuorum | ||
| // objects (member lists, vvec/contribution reads, quorum cache inserts) | ||
| // via ScanQuorums. Newest-first, matching ScanQuorums' ordering. | ||
| const auto& qbp{*context().llmq_ctx->quorum_block_processor}; | ||
| const auto quorum_base_block_indexes{llmq_params->useRotation | ||
| ? qbp.GetMinedCommitmentsIndexedUntilBlock(type, pindex, quorum_count) | ||
| : qbp.GetMinedCommitmentsUntilBlock(type, pindex, quorum_count)}; | ||
| for (const auto* pQuorumBaseBlockIndex : quorum_base_block_indexes) { | ||
| const auto qc{qbp.GetMinedCommitment(type, pQuorumBaseBlockIndex->GetBlockHash()).first}; | ||
| if (!qc.quorumPublicKey.IsValid()) continue; | ||
| ret.emplace_back(PlatformQuorum{ | ||
| .m_quorum_hash = qc.quorumHash, | ||
| .m_pubkey = qc.quorumPublicKey.ToByteVector(/*specificLegacyScheme=*/false), | ||
| .m_height = pQuorumBaseBlockIndex->nHeight, | ||
| }); | ||
| } | ||
| return ret; | ||
| } | ||
| std::vector<uint8_t> getInstantSendLock(const uint256& txid) override | ||
| { | ||
| if (!context().llmq_ctx || !context().llmq_ctx->isman) { | ||
| return {}; | ||
| } | ||
| const auto islock{context().llmq_ctx->isman->GetInstantSendLockByTxid(txid)}; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When SPORK_2 is disabled, or the node is reindexing/importing, this call returns empty for every txid because AGENTS.md reference: AGENTS.md:L169-L172 Useful? React with 👍 / 👎.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is fine; no action needed imo |
||
| if (!islock) { | ||
| return {}; | ||
| } | ||
| CDataStream ds(SER_NETWORK, PROTOCOL_VERSION); | ||
| ds << *islock; | ||
| return {UCharCast(ds.data()), UCharCast(ds.data()) + ds.size()}; | ||
| } | ||
| void setContext(NodeContext* context) override | ||
| { | ||
| m_context = context; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For EvoNodes whose state version predates
ProTxVersion::ExtAddr, the Platform endpoint is stored asplatformHTTPPortalongside the primary Core address rather than as aPLATFORM_HTTPSnetInfo entry (src/evo/dmnstate.h:112-115, with the conversion spelled out insrc/evo/specialtxman.cpp:471-473). This loop therefore returns an empty vector for valid legacy EvoNodes that have not submitted an extended-address update, removing those DAPI gateways from the GUI; synthesize the service from the primary address and legacy HTTP port whennetInfocannot store Platform entries.AGENTS.md reference: AGENTS.md:L15-L17
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Valid — fixed at the new head.
Confirmed against the code:
CDeterministicMNStateonly serializesplatformP2PPort/platformHTTPPortwhennVersion < ProTxVersion::ExtAddr(src/evo/dmnstate.h:112-115), andspecialtxman.cpp:471-478zeroes those scalars from ExtAddr onward precisely because netInfo owns them then. So the netInfo-only loop returned an empty vector for every legacy EvoNode — which today is most of them, meaning the GUI would have seen gateways only from nodes that had already submitted an extended-address update.getPlatformHTTPSAddrs()now branches on the state version: below ExtAddr it synthesizes the gateway from the primary address and the legacyplatformHTTPPort(guarded onMnType::Evoand a non-zero port, using the sameCService(addr, port)idiom asdmnstate.cpp:138andrpc/evo_util.h:41); at ExtAddr and above it reads thePLATFORM_HTTPSnetInfo entries as before.🤖 Posted autonomously by Claude on behalf of pasta.