Skip to content

refactor: expose masternode Platform endpoints, quorum keys and islocks via node interface - #7591

Open
PastaPastaPasta wants to merge 1 commit into
dashpay:developfrom
PastaPastaPasta:platform-node-seams
Open

refactor: expose masternode Platform endpoints, quorum keys and islocks via node interface#7591
PastaPastaPasta wants to merge 1 commit into
dashpay:developfrom
PastaPastaPasta:platform-node-seams

Conversation

@PastaPastaPasta

Copy link
Copy Markdown
Member

Issue being fixed or feature implemented

Part of the Dash Platform GUI train (#7512). dash-qt's Platform integration needs three pieces of node state that today have no interfaces::Node surface: evonode Platform HTTPS endpoints (to select DAPI gateways from the locally synced masternode list), locally retained Platform-quorum public keys (to verify Platform quorum signatures against local LLMQ data instead of trusting a remote key service), and InstantSend locks by txid (to build asset-lock proofs).

What was done?

Three read-only additions, compiled unconditionally (no Platform types, no feature gate):

  • MnEntry::getPlatformHTTPSAddrs() — the PLATFORM_HTTPS entries from the extended address list; empty for non-evo masternodes.
  • LLMQ::getPlatformQuorums(uint8_t llmq_type) — quorum hash, serialized basic-scheme BLS public key, and height for locally retained quorums, scanning max(signingActiveQuorumCount, keepOldKeys) so verification keeps working for proofs signed by recently rotated-out quorums.
  • LLMQ::getInstantSendLock(const uint256& txid) — serialized islock or empty.

These are exports of already-public node state (netInfo->GetEntries, qman->ScanQuorums, isman->GetInstantSendLockByTxid); no consensus surface, no key material, no behavior change for existing code.

Reference implementation using these seams: PastaPastaPasta#67.

How Has This Been Tested?

Compiles cleanly (node/libbitcoin_node_a-interfaces.o on macOS arm64 against depends). No other implementers of these interface classes exist in-tree (verified across src/test, src/qt/test, src/interfaces, src/ipc), so the pure-virtual additions require no stubs.

Breaking Changes

None.

…ks via node interface

Add three read-only exports of already-public node state to the node interface, needed by the Dash Platform GUI train (dashpay#7512): getPlatformHTTPSAddrs() returns the extended netinfo PLATFORM_HTTPS entries for a masternode-list entry, getPlatformQuorums() exports ScanQuorums results over the retained-key window with basic-scheme serialized quorum public keys, and getInstantSendLock() returns the serialized islock for a txid via GetInstantSendLockByTxid.

Reference implementation consuming these seams: #67. No consensus surface is touched, no key material is exposed, and everything is compiled unconditionally.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@thepastaclaw

thepastaclaw commented Aug 13, 2026

Copy link
Copy Markdown

⛔ Blockers found — Opus deferred (commit 8b6d630)
Canonical validated blockers: 1

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8b6d6307e8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/interfaces.cpp
Comment on lines +141 to +142
if (const auto service_opt{entry.GetAddrPort()}) {
ret.push_back(*service_opt);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve domain-based Platform HTTPS endpoints

When an EvoNode registers a valid domain endpoint such as example.com:443, GetAddrPort() returns empty because the entry contains a DomainPort, so this loop silently omits it. Platform HTTPS explicitly supports internet domains (as exercised in test/functional/rpc_netinfo.py), meaning the GUI can receive an incomplete or empty DAPI gateway list; expose both service and domain endpoint forms instead of restricting the interface to CService.

AGENTS.md reference: AGENTS.md:L172-L180

Useful? React with 👍 / 👎.

@coderabbitai

coderabbitai Bot commented Aug 13, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

The node interfaces now expose platform HTTPS addresses for Evo masternodes. LLMQ also exposes retained platform quorum hashes, serialized public keys, heights, and serialized InstantSend locks. Implementations collect valid platform addresses, scan retained quorum windows, exclude invalid public keys, and return empty results when required context or matching data is unavailable.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Mergeability Score: ⚪ Minimal · up to 8b6d6

The change adds read-only access to existing node state without a demonstrated production behavior or correctness regression. No actionable merge-blocking risk remains beyond normal checks and review.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the three node-interface additions for Platform endpoints, quorum keys, and InstantSend locks.
Description check ✅ Passed The description directly explains the implemented node-interface exports, their purpose, testing, and compatibility impact.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/node/interfaces.cpp`:
- Around line 137-146: Add targeted C++ unit tests covering the new interface
exports, including getPlatformHTTPSAddrs() handling invalid platform entries and
non-Evo entries, invalid LLMQ types and retained quorum selection, basic-scheme
public-key bytes, and serialized InstantSend locks. Use existing test fixtures
and assert the changed invariants so valid Platform proofs remain accepted and
asset-lock proofs serialize correctly.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e5330ff3-c927-4def-bf78-2c489eceafe3

📥 Commits

Reviewing files that changed from the base of the PR and between 76c38fa and 8b6d630.

📒 Files selected for processing (2)
  • src/interfaces/node.h
  • src/node/interfaces.cpp

Comment thread src/node/interfaces.cpp
Comment on lines +137 to +146
std::vector<CService> getPlatformHTTPSAddrs() const override
{
std::vector<CService> 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;
}

@coderabbitai coderabbitai Bot Aug 13, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

Add targeted coverage for the new interface exports.

No test changes cover the new endpoint, quorum, or InstantSend-lock behavior. Add tests for invalid platform entries, non-Evo entries, invalid LLMQ types, retained quorum selection, basic-scheme public-key bytes, and serialized locks. A regression here can cause the GUI to reject valid Platform proofs or build invalid asset-lock proofs.

As per coding guidelines, “Choose and add targeted C++ unit tests for changed behavior,” and quorum changes require small tests that prove the changed invariant.

Also applies to: 552-594

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/node/interfaces.cpp` around lines 137 - 146, Add targeted C++ unit tests
covering the new interface exports, including getPlatformHTTPSAddrs() handling
invalid platform entries and non-Evo entries, invalid LLMQ types and retained
quorum selection, basic-scheme public-key bytes, and serialized InstantSend
locks. Use existing test fixtures and assert the changed invariants so valid
Platform proofs remain accepted and asset-lock proofs serialize correctly.

Source: Coding guidelines

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The coverage request is valid, but endpoint tests must also include a valid DomainPort such as example.com:443. PLATFORM_HTTPS explicitly accepts DomainPort entries, while the current CService-only export silently drops them. The quorum test should also verify that exporting the retained window does not require materializing every full CQuorum object.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '== Network entry definitions and conversions =='
rg -n -A12 -B8 'GetAddrPort\s*\(|DomainPort|PLATFORM_HTTPS' src --glob '*.{h,cpp}'

printf '%s\n' '== Quorum scan declarations and implementations =='
rg -n -A18 -B10 'ScanQuorums\s*\(' src --glob '*.{h,cpp}'

printf '%s\n' '== Existing interface and quorum-related tests =='
fd -t f . src test 2>/dev/null | rg '(interfaces|quorum|llmq|deterministicmn|netinfo).*(_tests)?\.(cpp|h)$' | head -100
rg -n -A8 -B5 '(GetEntries|PLATFORM_HTTPS|DomainPort|ScanQuorums)' src test --glob '*_tests.cpp' --glob '*.cpp' 2>/dev/null | head -240

Length of output: 152096


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '== ScanQuorums implementation =='
sed -n '177,285p' src/llmq/quorumsman.cpp

printf '%s\n' '== Quorum construction and lightweight commitment retrieval =='
sed -n '168,235p' src/llmq/quorumsman.h
rg -n -A16 -B8 '(BuildQuorumFromCommitment|GetMinedCommitment|GetFinalCommitment|Read.*Commitment|CFinalCommitment)' src/llmq src/evo --glob '*.{h,cpp}' | head -300

printf '%s\n' '== Public interface contract =='
rg -n -A25 -B8 'getPlatformHTTPSAddrs|PlatformQuorum|getPlatformQuorums' src/interfaces/node.h

Length of output: 34197


@thepastaclaw, confirmed.

PLATFORM_HTTPS accepts DomainPort. Existing tests validate example.com:443. getPlatformHTTPSAddrs() cannot return this value because its public type is std::vector<CService> and its implementation only uses GetAddrPort(). The fix must change the interface contract and implementation to preserve both CService and DomainPort endpoints. The tests must assert that both endpoint types are exported.

getPlatformQuorums() also currently calls CQuorumManager::ScanQuorums(). That method calls GetQuorum() for every retained result. It therefore materializes full CQuorum objects and their member lists. The fix needs a lightweight retained-commitment query that returns the quorum hash, basic-scheme public key bytes, and base height without constructing CQuorum.

I will keep this finding open with the expanded scope.

🧐🐇


✏️ Learnings added
Learnt from: thepastaclaw
Repo: dashpay/dash PR: 7591
File: src/node/interfaces.cpp:137-146
Timestamp: 2026-08-13T03:37:37.236Z
Learning: For Dash Platform endpoint exports, `NetInfoPurpose::PLATFORM_HTTPS` can contain either `CService` or `DomainPort` entries. In particular, `example.com:443` is valid. An `interfaces::MnEntry` accessor for Platform HTTPS endpoints must preserve both types; a `std::vector<CService>` return type silently drops valid `DomainPort` entries.

Learnt from: thepastaclaw
Repo: dashpay/dash PR: 7591
File: src/node/interfaces.cpp:137-146
Timestamp: 2026-08-13T03:37:37.236Z
Learning: In `src/llmq/quorumsman.cpp`, `CQuorumManager::ScanQuorums()` materializes each result through `GetQuorum()`, including full `CQuorum` member data. An interface that exports only retained quorum hash, basic-scheme public key bytes, and height should use a lightweight retained-commitment enumeration path instead of `ScanQuorums()`.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

You are interacting with an AI system.

@thepastaclaw thepastaclaw left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Preliminary review — Codex only

The InstantSend-lock export and basic-scheme quorum-key serialization are consistent with existing node behavior. The Platform endpoint contract omits valid DNS gateways, while quorum enumeration synchronously materializes up to 1,440 full quorum objects; targeted tests for these new interface contracts are also absent.
Source: reviewer backend model gpt-5.6-sol; final verifier backend model gpt-5.6-sol; openclaw-agent/cliproxy/gpt-5.6-sol is orchestration-only and not reviewer evidence.

Validated blockers were found in the Codex precheck. Opus is deferred until a fresh Codex revalidation clears the blocker gate.

Review provenance

  • Codex reviewers: gpt-5.6-sol — general (completed)
  • Verifier: gpt-5.6-sol — verifier
  • Sonnet: not run (deferred by blocker gate)

🔴 1 blocking | 🟡 2 suggestion(s)

🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.

In `src/node/interfaces.cpp`:
- [BLOCKING] src/node/interfaces.cpp:140-143: Preserve domain-based Platform HTTPS endpoints
  `PLATFORM_HTTPS` entries may contain either a `CService` or a `DomainPort`. `ExtNetInfo::ProcessCandidate()` explicitly permits domains for this purpose, and the netinfo tests accept entries such as `example.com:443`. `GetAddrPort()` returns `std::nullopt` for every `DomainPort`, so this implementation silently drops valid DAPI gateways. Because the interface returns only `std::vector<CService>`, callers cannot recover the omitted hostname, leaving the GUI with an incomplete or empty gateway set for evonodes that advertise DNS endpoints. Expose a representation that preserves both endpoint variants, such as a validated host-and-port string or a dedicated endpoint variant.
- [SUGGESTION] src/node/interfaces.cpp:570-572: Avoid constructing full quorums just to export public keys
  Platform quorum parameters retain 24 × 30 × 2 = 1,440 quorum keys. `ScanQuorums()` materializes a `CQuorum` for every uncached commitment: `BuildQuorumFromCommitment()` computes the full member list, reads or rebuilds contribution and verification-vector data, and unconditionally inserts the resulting object into `mapQuorumsCache`, whose per-type capacity is initialized from `keepOldKeys`. The new API only needs the quorum hash, public key, and base height, but its initial GUI-thread invocation can therefore build and retain two months of full quorum objects, and the reference consumer refreshes this context every minute. Add a lightweight quorum-manager export that scans mined commitments and returns these three fields without constructing `CQuorum` instances.
- [SUGGESTION] src/node/interfaces.cpp:137-146: Add targeted coverage for the new interface exports
  The PR introduces three externally consumed interface contracts but adds no tests beyond a compile check. Add focused tests for non-evo and missing-context results, valid `CService` and `DomainPort` HTTPS entries, unsupported LLMQ types, the retained-quorum window, basic-scheme public-key bytes, and exact InstantSend-lock serialization with the missing-lock case. In particular, a valid domain-endpoint test would expose the current loss of DNS gateways, while serialization assertions would prevent subtle incompatibilities in Platform proof and asset-lock construction.

Comment thread src/node/interfaces.cpp
Comment on lines +140 to +143
for (const auto& entry : m_dmn->pdmnState->netInfo->GetEntries(NetInfoPurpose::PLATFORM_HTTPS)) {
if (const auto service_opt{entry.GetAddrPort()}) {
ret.push_back(*service_opt);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Blocking: Preserve domain-based Platform HTTPS endpoints

PLATFORM_HTTPS entries may contain either a CService or a DomainPort. ExtNetInfo::ProcessCandidate() explicitly permits domains for this purpose, and the netinfo tests accept entries such as example.com:443. GetAddrPort() returns std::nullopt for every DomainPort, so this implementation silently drops valid DAPI gateways. Because the interface returns only std::vector<CService>, callers cannot recover the omitted hostname, leaving the GUI with an incomplete or empty gateway set for evonodes that advertise DNS endpoints. Expose a representation that preserves both endpoint variants, such as a validated host-and-port string or a dedicated endpoint variant.

source: ['codex']

Comment thread src/node/interfaces.cpp
Comment on lines +570 to +572
const auto quorum_count{static_cast<size_t>(std::max(llmq_params->signingActiveQuorumCount,
llmq_params->keepOldKeys))};
for (const auto& q : context().llmq_ctx->qman->ScanQuorums(type, pindex, quorum_count)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Suggestion: Avoid constructing full quorums just to export public keys

Platform quorum parameters retain 24 × 30 × 2 = 1,440 quorum keys. ScanQuorums() materializes a CQuorum for every uncached commitment: BuildQuorumFromCommitment() computes the full member list, reads or rebuilds contribution and verification-vector data, and unconditionally inserts the resulting object into mapQuorumsCache, whose per-type capacity is initialized from keepOldKeys. The new API only needs the quorum hash, public key, and base height, but its initial GUI-thread invocation can therefore build and retain two months of full quorum objects, and the reference consumer refreshes this context every minute. Add a lightweight quorum-manager export that scans mined commitments and returns these three fields without constructing CQuorum instances.

source: ['codex']

Comment thread src/node/interfaces.cpp
Comment on lines +137 to +146
std::vector<CService> getPlatformHTTPSAddrs() const override
{
std::vector<CService> 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;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Suggestion: Add targeted coverage for the new interface exports

The PR introduces three externally consumed interface contracts but adds no tests beyond a compile check. Add focused tests for non-evo and missing-context results, valid CService and DomainPort HTTPS entries, unsupported LLMQ types, the retained-quorum window, basic-scheme public-key bytes, and exact InstantSend-lock serialization with the missing-lock case. In particular, a valid domain-endpoint test would expose the current loss of DNS gateways, while serialization assertions would prevent subtle incompatibilities in Platform proof and asset-lock construction.

source: ['coderabbit']

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants