Skip to content

feat(dash-spv): devnet LLMQ routing overrides (chainlocks/isd24/platform)#786

Draft
thepastaclaw wants to merge 2 commits into
dashpay:devfrom
thepastaclaw:fix/issue-785-devnet-llmq-routing-overrides
Draft

feat(dash-spv): devnet LLMQ routing overrides (chainlocks/isd24/platform)#786
thepastaclaw wants to merge 2 commits into
dashpay:devfrom
thepastaclaw:fix/issue-785-devnet-llmq-routing-overrides

Conversation

@thepastaclaw
Copy link
Copy Markdown
Contributor

@thepastaclaw thepastaclaw commented May 27, 2026

Summary

Closes #785. Adds support for Dash Core's devnet LLMQ routing overrides — -llmqchainlocks, -llmqinstantsenddip0024, and -llmqplatform — so a dash-spv client can talk to small devnets that reroute these roles onto LLMQ_DEVNET (or another devnet quorum type).

Implementation follows PR #784's pragmatic Option B: three new process-global OnceLocks with idempotent setters, mirroring the established set_llmq_devnet_params contract.

  • dash/src/sml/llmq_type/mod.rs — new statics DEVNET_CHAIN_LOCKS_OVERRIDE / DEVNET_ISD_OVERRIDE / DEVNET_PLATFORM_OVERRIDE; helpers set_devnet_chain_locks_type / set_devnet_isd_type / set_devnet_platform_type; getters devnet_*_override(); Dash-Core-name parser devnet_llmq_type_from_name accepting llmq_devnet, llmq_devnet_dip0024, llmq_devnet_platform (plus this crate's llmq_dev_platform spelling).
  • dash/src/sml/llmq_type/network.rsNetworkLLMQExt::{chain_locks_type, isd_llmq_type, platform_type} honor the overrides on Devnet only. Mainnet/testnet/regtest arms are untouched. enabled_llmq_types stays as the three default devnet types — setters already reject anything outside that set, so overrides are a strict subset.
  • dash-spv/src/client/config.rsClientConfig gains llmq_chainlocks_type / llmq_instantsend_dip0024_type / llmq_platform_type, matching builders, validate() devnet-only rejection, and wiring through apply_global_overrides().
  • dash-spv/src/main.rs — new CLI flags --llmq-chainlocks, --llmq-instantsend-dip0024, --llmq-platform, each rejected on non-devnet networks.

Acceptance criteria

  • CLI accepts the three flags; rejected on non-devnet networks
  • ClientConfig carries the overrides through to startup (apply_global_overrides)
  • chain_locks_type / isd_llmq_type / platform_type return the overridden values on Devnet when set
  • enabled_llmq_types covers the overridden types (already does — override domain is a subset of the default devnet list)
  • Unit tests cover override-set / override-unset / cross-network rejection
  • Existing PR feat: devnet support for dash-spv #784 test test_llmq_devnet_override_lifecycle stays green

Validation

  • cargo test -p dashcore --lib sml::llmq_type — 15 passed (4 new: parser, non-devnet-type rejection, three role lifecycle tests; existing devnet-params lifecycle still green).
  • cargo test -p dash-spv --lib client::config — 12 passed (4 new: builder coverage + three cross-network rejection tests).
  • cargo test -p dashcore --lib — 546 passed, 0 failed, 15 ignored.
  • cargo test -p dash-spv --lib — 441 passed, 0 failed, 2 ignored.
  • cargo fmt -p dashcore -p dash-spv --check clean.
  • cargo clippy -p dashcore -p dash-spv --all-targets -- -D warnings clean.
  • cargo run -p dash-spv --bin dash-spv -- --help shows the three new flags under their Dash-Core-named forms.

Test plan

  • CI green
  • Smoke against a small devnet that reroutes -llmqinstantsenddip0024=llmq_devnet to confirm InstantSend locks verify
  • CodeRabbit review

Notes

  • The OnceLock pattern carries the same process-global limitation as PR feat: devnet support for dash-spv #784: once set, the override is sticky for the lifetime of the process. Conflict re-sets error; identical re-sets are idempotent.
  • Out of scope (flagged by review for a follow-up): impl From<u8> for LLMQType in dash/src/sml/llmq_type/mod.rs is missing the 107 => LlmqtypeDevnetPlatform arm — a pre-existing decoder gap unrelated to this PR, but now relevant if Platform routing is exercised on the wire.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added devnet-specific LLMQ quorum routing overrides for ChainLocks, InstantSend DIP24, and Platform.
    • New CLI arguments allow custom quorum type configuration on devnet networks.
    • Integrated validation restricts overrides to devnet-only usage.

Review Change Stack

…atform

Mirror Dash Core's `-llmqchainlocks`, `-llmqinstantsenddip0024`, and
`-llmqplatform` flags so an SPV client can talk to small devnets that
reroute these roles onto `LLMQ_DEVNET` (or any other devnet quorum
type). Extends PR dashpay#784's OnceLock override pattern (Option B from the
issue) with three new process-global slots.

- Add `set_devnet_chain_locks_type`, `set_devnet_isd_type`,
  `set_devnet_platform_type`, their `*_override()` getters, and the
  Dash-Core-compatible name parser `devnet_llmq_type_from_name`.
- Apply the overrides in `NetworkLLMQExt::{chain_locks_type,
  isd_llmq_type, platform_type}` for Devnet only; mainnet/testnet/
  regtest routing is untouched.
- `enabled_llmq_types` stays as the three default devnet types —
  setters reject non-devnet LLMQ types, so overrides are already a
  subset.
- Surface the three knobs through `ClientConfig` builders, validate
  them as devnet-only, and apply them in `apply_global_overrides`.
- New CLI flags `--llmq-chainlocks`, `--llmq-instantsend-dip0024`,
  `--llmq-platform`, rejected on non-devnet networks.
- Tests cover the parser, the setter lifecycle (set/idempotent/
  conflict) via NetworkLLMQExt, non-devnet-type rejection, and
  cross-network `ClientConfig` rejection.

Closes dashpay#785

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@thepastaclaw
Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 27, 2026

Warning

Review limit reached

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

More reviews will be available in 27 minutes and 35 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: 7209f90e-1a70-4ffe-82f6-f1991aed2580

📥 Commits

Reviewing files that changed from the base of the PR and between 8117861 and cf2571a.

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

Walkthrough

This PR adds devnet-only LLMQ routing overrides to allow small devnets to reroute ChainLocks, InstantSend DIP24, and Platform quorums onto a custom LLMQ type. The feature flows from process-global override storage through network routing, client configuration, and CLI argument parsing, enabling parity with Dash Core's -llmqchainlocks, -llmqinstantsenddip0024, and -llmqplatform flags.

Changes

Devnet LLMQ Routing Overrides

Layer / File(s) Summary
Devnet LLMQ override storage and resolver
dash/src/sml/llmq_type/mod.rs
Introduces OnceLock-backed process-global storage for ChainLocks, InstantSend DIP24, and Platform LLMQ type overrides. devnet_llmq_type_from_name parses Dash Core quorum name strings (including llmq_devnet_platform / llmq_dev_platform spelling variants). Setter functions enforce idempotent identity and reject conflicting re-sets; getter functions return the effective override or None. Tests verify name resolution, override lifecycle (set, idempotent re-set, conflicting re-set rejection), and per-network routing behavior.
Network routing integration with overrides
dash/src/sml/llmq_type/network.rs
Updates NetworkLLMQExt methods (isd_llmq_type, chain_locks_type, platform_type) to query devnet override getters and fall back to hardcoded defaults when no override is set. Documentation clarifies that setter validation covers all override values.
ClientConfig devnet override fields and validation
dash-spv/src/client/config.rs
Extends ClientConfig with three optional LLMQ routing override fields and builder methods (with_llmq_chainlocks_type, with_llmq_instantsend_dip0024_type, with_llmq_platform_type). Validation rejects overrides on non-devnet networks. apply_global_overrides() calls setter functions for each configured override. Unit tests verify devnet-only acceptance and builder method behavior.
CLI argument parsing and validation
dash-spv/src/main.rs
Adds three new CLI arguments accepting Dash Core quorum name strings. On devnet, names are resolved via devnet_llmq_type_from_name and applied to ClientConfig using builder methods with logging. On other networks, all three arguments are rejected with specific error messages.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • dashpay/rust-dashcore#784: Both PRs extend devnet-only configuration in ClientConfig with validation and global override application during startup, using parallel patterns for llmq_devnet_params and the per-quorum routing type overrides.

Suggested reviewers

  • QuantumExplorer

Poem

🐇 A devnet springs to life with routed quorums bright,
ChainLocks and Platform dancing through the night,
Small master nodes now find their way to fame,
No more the silent fail—each lock's aflame!

🚥 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 summarizes the main change: adding devnet LLMQ routing overrides for chainlocks, instantsend DIP24, and platform.
Linked Issues check ✅ Passed All coding requirements from issue #785 are met: CLI flags implemented, ClientConfig updated, routing overrides threaded through, enabled_llmq_types includes overridden types, and comprehensive unit tests added.
Out of Scope Changes check ✅ Passed All changes directly address the #785 requirements; no unrelated modifications detected. Implementation stays devnet-only and preserves mainnet/testnet/regtest behavior.
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

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.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 27, 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.

🧹 Nitpick comments (1)
dash/src/sml/llmq_type/mod.rs (1)

518-537: ⚡ Quick win

Pre-existing: From<u8> is missing the arm for 107 (LlmqtypeDevnetPlatform).

The PR notes already flag this as out-of-scope follow-up. Currently 107_u8 maps to LlmqtypeUnknown. This won't block devnet override functionality since overrides are set by name, but consensus decoding of quorum commitments using type 107 will misparse.

Suggested fix
             105 => LLMQType::LlmqtypeDevnetDIP0024,
             106 => LLMQType::LlmqtypeTestnetPlatform,
+            107 => LLMQType::LlmqtypeDevnetPlatform,
             _ => LLMQType::LlmqtypeUnknown,
🤖 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 `@dash/src/sml/llmq_type/mod.rs` around lines 518 - 537, The From<u8>
implementation for LLMQType is missing the match arm for value 107, so bytes
with value 107 currently fall through to LlmqtypeUnknown; update the match in
impl From<u8> for LLMQType to include a branch mapping 107 =>
LLMQType::LlmqtypeDevnetPlatform (matching the enum variant name
LlmqtypeDevnetPlatform) so that decoding of quorum types correctly recognizes
devnet platform type 107.
🤖 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.

Nitpick comments:
In `@dash/src/sml/llmq_type/mod.rs`:
- Around line 518-537: The From<u8> implementation for LLMQType is missing the
match arm for value 107, so bytes with value 107 currently fall through to
LlmqtypeUnknown; update the match in impl From<u8> for LLMQType to include a
branch mapping 107 => LLMQType::LlmqtypeDevnetPlatform (matching the enum
variant name LlmqtypeDevnetPlatform) so that decoding of quorum types correctly
recognizes devnet platform type 107.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 67b60436-4fbf-4f6d-a74c-5b1429748a25

📥 Commits

Reviewing files that changed from the base of the PR and between 58d61ea and 8117861.

📒 Files selected for processing (4)
  • dash-spv/src/client/config.rs
  • dash-spv/src/main.rs
  • dash/src/sml/llmq_type/mod.rs
  • dash/src/sml/llmq_type/network.rs

coderabbitai[bot]
coderabbitai Bot previously approved these changes May 27, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented May 27, 2026

Codecov Report

❌ Patch coverage is 86.17512% with 30 lines in your changes missing coverage. Please review.
✅ Project coverage is 72.31%. Comparing base (58d61ea) to head (8117861).

Files with missing lines Patch % Lines
dash-spv/src/main.rs 0.00% 27 Missing ⚠️
dash-spv/src/client/config.rs 96.38% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##              dev     #786      +/-   ##
==========================================
+ Coverage   72.21%   72.31%   +0.09%     
==========================================
  Files         321      321              
  Lines       70467    70681     +214     
==========================================
+ Hits        50890    51115     +225     
+ Misses      19577    19566      -11     
Flag Coverage Δ
core 76.49% <100.00%> (+0.15%) ⬆️
ffi 46.21% <ø> (+0.01%) ⬆️
rpc 20.00% <ø> (ø)
spv 89.54% <72.72%> (+0.05%) ⬆️
wallet 71.21% <ø> (ø)
Files with missing lines Coverage Δ
dash/src/sml/llmq_type/mod.rs 79.72% <100.00%> (+8.07%) ⬆️
dash/src/sml/llmq_type/network.rs 85.56% <100.00%> (+12.37%) ⬆️
dash-spv/src/client/config.rs 91.97% <96.38%> (+3.51%) ⬆️
dash-spv/src/main.rs 0.00% <0.00%> (ø)

... and 6 files with indirect coverage changes

@thepastaclaw
Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 27, 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 Author

@thepastaclaw thepastaclaw left a comment

Choose a reason for hiding this comment

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

Code Review

Clean, scoped PR that mirrors the existing set_llmq_devnet_params OnceLock pattern for three additional devnet routing slots. The fix commit closes a real decoder gap for LlmqtypeDevnetPlatform (107). One suggestion: ClientConfig::validate() accepts impossible quorum types for the new override fields and only fails later in apply_global_overrides() at client startup, after validate() has already created the storage directory.

🟡 1 suggestion(s)

1 additional finding(s) omitted (not in diff).

🤖 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 `dash-spv/src/client/config.rs`:
- [SUGGESTION] dash-spv/src/client/config.rs:236-275: `validate()` doesn't reject invalid LLMQ types for the new override fields
  On devnet, `validate()` only checks that the network is `Devnet`; it never checks whether `llmq_chainlocks_type` / `llmq_instantsend_dip0024_type` / `llmq_platform_type` actually hold a devnet-routable quorum. A programmatic caller can therefore build `ClientConfig::new(Network::Devnet).with_llmq_chainlocks_type(LLMQType::Llmqtype50_60)`, get `Ok(())` from `validate()` (after `validate()` has already invoked `create_dir_all` on the storage path), and only hit the real domain check later when `apply_global_overrides()` runs during client startup via `set_devnet_*_type()`. The CLI path is safe because it parses through `devnet_llmq_type_from_name()`, but the public Rust builder API exposes the wider surface and the validation contract becomes misleading. Mirror the domain check from `set_devnet_routing_override` inside `validate()` so misconfiguration surfaces before any side effects.

@github-actions github-actions Bot added the merge-conflict The PR conflicts with the target branch. label May 28, 2026
@github-actions
Copy link
Copy Markdown
Contributor

This PR has merge conflicts with the base branch. Please rebase or merge the base branch into your branch to resolve them.

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

Labels

merge-conflict The PR conflicts with the target branch.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

dash-spv: support Dash Core's devnet LLMQ routing overrides (-llmqchainlocks / -llmqinstantsenddip0024 / -llmqplatform)

1 participant