Skip to content

fix: resolve just-retired quorum by walking earlier masternode lists#801

Open
xdustinface wants to merge 3 commits into
devfrom
fix/quorum-lookup-retired-quorum
Open

fix: resolve just-retired quorum by walking earlier masternode lists#801
xdustinface wants to merge 3 commits into
devfrom
fix/quorum-lookup-retired-quorum

Conversation

@xdustinface
Copy link
Copy Markdown
Collaborator

@xdustinface xdustinface commented Jun 2, 2026

get_quorum_at_height and the FFI ffi_dash_spv_get_quorum_public_key resolved a quorum only through the single nearest masternode list at or below the lookup height. A Platform signing quorum is selected at a lagged height, so by the proof's core_chain_locked_height it can already have retired out of the active set. apply_diff drops a retired quorum from every later list, so the nearest list misses and the lookup fails with Quorum not found, surfacing downstream as InvalidQuorum. The failure is intermittent, firing only at the retirement edge.

The full entry is not actually gone: apply_diff clones the base list without mutating earlier ones, and old per-height lists are retained, so the quorum still lives in every list from its mint height up to retirement.

Add MasternodeListEngine::quorum_entry_for_hash_at_or_before_height, which walks masternode_lists backward from the lookup height and returns the first list still holding the quorum, skipping Invalid entries. Both consumer sites route through it, so the real full QualifiedQuorumEntry is returned with no synthesized data, no new storage, and no API change. The walk is floored at a few active windows below the height (derived from the type's signing_active_quorum_count and DKG interval): a legitimately referenced signing quorum cannot be older than that, so a miss scans a bounded span rather than every accumulated list.

Closes #800.

Summary by CodeRabbit

  • Bug Fixes
    • Improved quorum resolution across block heights for more reliable lookups (better handling of older/retired quorums).
    • More concise and informative error messages when quorum resolution fails, including quorum type, requested height, and quorum identifier.

`get_quorum_at_height` and the FFI `ffi_dash_spv_get_quorum_public_key` resolved a quorum only through the single nearest masternode list at or below the lookup height. A Platform signing quorum is selected at a lagged height, so by the proof's `core_chain_locked_height` it can already have retired out of the active set. `apply_diff` drops a retired quorum from every later list, so the nearest list misses and the lookup fails with `Quorum not found`, surfacing downstream as `InvalidQuorum`. The failure is intermittent, firing only at the retirement edge.

The full entry is not actually gone: `apply_diff` clones the base list without mutating earlier ones, and old per-height lists are retained, so the quorum still lives in every list from its mint height up to retirement.

Add `MasternodeListEngine::quorum_entry_for_hash_at_or_before_height`, which walks `masternode_lists` backward from the lookup height and returns the first list still holding the quorum, skipping `Invalid` entries. Both consumer sites route through it, so the real full `QualifiedQuorumEntry` is returned with no synthesized data, no new storage, and no API change. The walk is floored at a few active windows below the height (derived from the type's `signing_active_quorum_count` and DKG interval): a legitimately referenced signing quorum cannot be older than that, so a miss scans a bounded span rather than every accumulated list.

Closes #800.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 2, 2026

Review Change Stack

Warning

Review limit reached

@xdustinface, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 52 minutes and 59 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 9d76ff6c-9be0-4309-9e18-f277863e0488

📥 Commits

Reviewing files that changed from the base of the PR and between a241cc3 and 57ae73d.

📒 Files selected for processing (1)
  • dash/src/sml/masternode_list_engine/helpers.rs
📝 Walkthrough

Walkthrough

This PR introduces a new quorum lookup API in MasternodeListEngine::quorum_entry_for_hash_at_or_before_height() that searches retained masternode lists within a computed active-window floor, and refactors both the dash-spv client library and FFI layers to use this direct hash-based resolution instead of manual list iteration.

Changes

Quorum hash-based lookup refactor

Layer / File(s) Summary
Quorum lookup engine and windowing
dash/src/sml/masternode_list_engine/helpers.rs
Adds QUORUM_WALK_BACK_ACTIVE_WINDOWS constant and quorum_entry_for_hash_at_or_before_height() function that computes an active-window floor from LLMQType parameters, iterates retained masternode lists in descending order, filters out Invalid entries, and returns the originating list height with the resolved QualifiedQuorumEntry. Includes tests for active/retired quorum resolution, absence cases, Invalid-entry skipping, and active-window boundary enforcement.
Dash-spv client queries refactor
dash-spv/src/client/queries.rs
get_quorum_at_height() now calls quorum_entry_for_hash_at_or_before_height() directly instead of manually constructing masternode lists and searching nested quorum maps. Returns the cloned quorum on match with debug logging; on miss, emits a single warning and returns SpvError::QuorumLookupError with a simplified error message.
FFI platform integration refactor
dash-spv-ffi/src/platform_integration.rs
ffi_dash_spv_get_quorum_public_key() now resolves the quorum entry via quorum_entry_for_hash_at_or_before_height(), copies the 48-byte public key to out_pubkey on success, and returns ValidationError with a focused message (quorum type, height, hash) on miss.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A quorum sought through time and hash,
Now walks the windows back with dash,
No list-by-list, just one clean call—
The hash unlocks the quorum's hall!
Retired or new, we find them all.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding backward masternode list walking to resolve retired quorums.
Linked Issues check ✅ Passed The PR addresses issue #800 by implementing quorum lookup that works for retired quorums, though using backward walking instead of the suggested fallback approach.
Out of Scope Changes check ✅ Passed All changes are scoped to quorum lookup logic and directly support the primary objective of resolving just-retired quorums.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/quorum-lookup-retired-quorum

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@xdustinface xdustinface marked this pull request as ready for review June 2, 2026 17:13
@xdustinface
Copy link
Copy Markdown
Collaborator Author

@CodeRabbit review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 2, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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 `@dash-spv/src/client/queries.rs`:
- Line 78: The tracing::warn!(message) call treats message as a structured
field; change the tracing::warn! invocation that references the variable message
to use a format string (e.g., tracing::warn!("{}", message)) or the formatter
shorthand (tracing::warn!(%message)) so the text is emitted as the event message
to match the tracing::debug(...) style; update the invocation where
tracing::warn! is called with the local variable message.

In `@dash/src/sml/masternode_list_engine/helpers.rs`:
- Around line 96-101: Remove the redundant QuorumHash import in the test module:
the tests module already brings QuorumHash into scope via use super::*, so
update the use crate::{BlockHash, QuorumHash}; line (inside #[cfg(test)] mod
tests) to only import BlockHash (e.g., use crate::BlockHash;) or otherwise omit
QuorumHash, leaving functions/structs that reference QuorumHash untouched;
reference the test module and the use statement near the top of helpers.rs to
locate and edit the import.
🪄 Autofix (Beta)

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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 3fa92136-d9bf-4610-a80f-1de727fbf6c4

📥 Commits

Reviewing files that changed from the base of the PR and between a132945 and db34dfc.

📒 Files selected for processing (3)
  • dash-spv-ffi/src/platform_integration.rs
  • dash-spv/src/client/queries.rs
  • dash/src/sml/masternode_list_engine/helpers.rs

Comment thread dash-spv/src/client/queries.rs Outdated
Comment thread dash/src/sml/masternode_list_engine/helpers.rs Outdated
@codecov
Copy link
Copy Markdown

codecov Bot commented Jun 2, 2026

Codecov Report

❌ Patch coverage is 82.43243% with 26 lines in your changes missing coverage. Please review.
✅ Project coverage is 72.73%. Comparing base (a132945) to head (57ae73d).

Files with missing lines Patch % Lines
dash-spv-ffi/src/platform_integration.rs 0.00% 13 Missing ⚠️
dash-spv/src/client/queries.rs 0.00% 13 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##              dev     #801      +/-   ##
==========================================
+ Coverage   72.67%   72.73%   +0.05%     
==========================================
  Files         322      322              
  Lines       71363    71454      +91     
==========================================
+ Hits        51866    51969     +103     
+ Misses      19497    19485      -12     
Flag Coverage Δ
core 76.71% <100.00%> (+0.17%) ⬆️
ffi 46.30% <0.00%> (-0.11%) ⬇️
rpc 20.00% <ø> (ø)
spv 90.28% <0.00%> (-0.02%) ⬇️
wallet 71.29% <ø> (ø)
Files with missing lines Coverage Δ
dash/src/sml/masternode_list_engine/helpers.rs 100.00% <100.00%> (ø)
dash-spv-ffi/src/platform_integration.rs 27.47% <0.00%> (+4.74%) ⬆️
dash-spv/src/client/queries.rs 21.21% <0.00%> (+5.65%) ⬆️

... and 25 files with indirect coverage changes

…rum lookup

Addresses CodeRabbit review comment on PR #801
#801 (comment)
xdustinface added a commit that referenced this pull request Jun 4, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 4, 2026
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.

dash-spv: get_quorum_at_height fails for a just-retired Platform quorum (InvalidQuorum) though the pubkey is resident in quorum_statuses

1 participant