Skip to content

refactor: follow-up cleanups for #7473 (comments, defensive guard) - #7555

Merged
PastaPastaPasta merged 2 commits into
dashpay:developfrom
PastaPastaPasta:refactor/7473-followups
Aug 7, 2026
Merged

refactor: follow-up cleanups for #7473 (comments, defensive guard)#7555
PastaPastaPasta merged 2 commits into
dashpay:developfrom
PastaPastaPasta:refactor/7473-followups

Conversation

@PastaPastaPasta

Copy link
Copy Markdown
Member

Issue being fixed or feature implemented

Review follow-up cleanups to PR #7473 ("fix: correct masternode operator key BLS scheme handling"). There are no consensus or behavior changes introduced by this PR (the defensive guard in HasOperatorKeyUnderAnyScheme is unreachable with current callers).

What was done?

  • Redistributed the consolidated comment block in src/test/evo_deterministicmns_tests.cpp to sit directly above the individual test functions they describe, and removed the "Codex P1:" attribution prefix.
  • Added a defensive if (!pubkey.IsValid()) return false; check in CDeterministicMNList::HasOperatorKeyUnderAnyScheme (src/evo/deterministicmns.h).
  • Recorded the safety argument in src/txmempool.cpp for why skipping same-key migrations in existsProviderTxCrossSchemeConflict is safe and necessary.
  • Hardened TestMNChainSetup::MineToV24 in src/test/evo_deterministicmns_tests.cpp with BOOST_REQUIRE(IsV24Active()) and cleaned up redundant post-call check lines.

How Has This Been Tested?

  • Built src/test/test_dash cleanly.
  • Executed ./src/test/test_dash --run_test=evo_dip3_activation_tests (evo_deterministicmns_tests.cpp suite, 36 test cases passed).
  • Executed test/lint/lint-whitespace.py (0 errors).

Breaking Changes

None.

Checklist:

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have made corresponding changes to the documentation
  • I have assigned this pull request to a milestone

This pull request was created by Codex.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@thepastaclaw

thepastaclaw commented Aug 7, 2026

Copy link
Copy Markdown

🕓 Ready for review — 4 ahead in queue (commit 4084b73)
Queue position: 5/8 · 1 review active
ETA: start ~20:49 UTC · complete ~21:09 UTC (median 19m across 30 recent reviews; 2 slots)
Queued 9m ago · Last checked: 2026-08-07 20:10 UTC

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ea336b98-e6cd-43c4-8d70-e117c08d27e6

📥 Commits

Reviewing files that changed from the base of the PR and between 8262905 and 4084b73.

📒 Files selected for processing (2)
  • src/evo/deterministicmns.h
  • src/test/evo_deterministicmns_tests.cpp
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/evo/deterministicmns.h
  • src/test/evo_deterministicmns_tests.cpp

Walkthrough

The change makes HasOperatorKeyUnderAnyScheme reject invalid BLS public keys before checking key encodings. Tests centralize v24 activation validation and document regression coverage for operator-key migrations, cross-scheme conflicts, mempool races, key reuse, lookup behavior, pre-v24 behavior, and stale transactions. The mempool conflict-check comment now explains same-key migration handling.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

  • dashpay/dash#7302: Adds related validation and regression coverage for v24 ProTx version and key-scheme migrations.
  • dashpay/dash#7437: Covers related v24 shared-masternode operator-key encoding and conflict handling.

Suggested reviewers: udjinm6

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies follow-up cleanup work for PR #7473, including comment changes and a defensive guard.
Description check ✅ Passed The description directly explains the cleanup, defensive guard, mempool documentation, tests, and absence of behavior changes.
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.

🧹 Nitpick comments (1)
src/test/evo_deterministicmns_tests.cpp (1)

2549-2551: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Cover the invalid-key branch.

The new HasOperatorKeyUnderAnyScheme guard is not exercised by FuncHasOperatorKeyUnderAnyScheme. Add an invalid CBLSPublicKey case and assert that the helper returns false.

Suggested regression case
     BOOST_CHECK(!list.HasOperatorKeyUnderAnyScheme(other.GetPublicKey(), uint256()));
+    const CBLSPublicKey invalid_key{};
+    BOOST_CHECK(!list.HasOperatorKeyUnderAnyScheme(invalid_key, uint256()));

As per coding guidelines, add focused C++ coverage for the changed invariant in this existing test file.

🤖 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/test/evo_deterministicmns_tests.cpp` around lines 2549 - 2551, Add
focused coverage in FuncHasOperatorKeyUnderAnyScheme for an invalid
CBLSPublicKey, invoking the HasOperatorKeyUnderAnyScheme guard and asserting it
returns false. Keep the test scoped to this invalid-key branch and preserve the
existing valid-key assertions.

Source: Coding guidelines

🤖 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 `@src/test/evo_deterministicmns_tests.cpp`:
- Around line 2549-2551: Add focused coverage in
FuncHasOperatorKeyUnderAnyScheme for an invalid CBLSPublicKey, invoking the
HasOperatorKeyUnderAnyScheme guard and asserting it returns false. Keep the test
scoped to this invalid-key branch and preserve the existing valid-key
assertions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 96be6d0a-8194-495a-8b3a-681d900ce1f0

📥 Commits

Reviewing files that changed from the base of the PR and between 3c87ad2 and 8262905.

📒 Files selected for processing (3)
  • src/evo/deterministicmns.h
  • src/test/evo_deterministicmns_tests.cpp
  • src/txmempool.cpp

@PastaPastaPasta

Copy link
Copy Markdown
Member Author

This PR collects the minor, non-blocking findings from the review of #7473. None of them affected correctness — #7473 was merged as-is deliberately — but each one is worth fixing while the context is fresh. For the record, the findings and what this PR does about them:

1. Review-artifact comments in the test file. evo_deterministicmns_tests.cpp contained a ~48-line consolidated block of comments describing many different tests in one place (a leftover from moving the Func* definitions around during #7473's development), including a "Codex P1:" review-tool attribution. Comments addressed to a reviewer are noise once the PR merges. This PR redistributes every paragraph to sit directly above the test it describes (all 11 paragraphs accounted for, none lost) and drops the attribution prefix while keeping its technical content. Value: each test now carries its own rationale — including the non-retroactivity test's "fix the gating, not this test" warning, which future readers should see at that test, not 500 lines away.

2. HasOperatorKeyUnderAnyScheme did not reject an invalid pubkey. Its mempool counterpart (existsProviderTxCrossSchemeConflict's probe) starts with if (!pubkey.IsValid()) return false;, but the list helper didn't. An invalid key wrapped via Set() serializes as all-zero bytes, so the probe returned false only because AddUniqueProperty happens to never admit a null value into the map — correct by invariant rather than by construction. All current callers pass validated or stored-valid keys, so this is unreachable today; the added guard makes the helper self-contained and consistent with its twin. No behavior change.

3. The mempool same-key skip was documented inaccurately. existsProviderTxCrossSchemeConflict skips the cross-scheme probe when a ProUpRegTx keeps its own operator key, and the old comment said this was "matching the consensus checks" — but #7473's consensus checks do probe same-key scheme migrations, so the policy/consensus asymmetry existed without its safety argument written down anywhere. The replacement comment records why the skip is safe (a same-encoding in-flight claim is caught by existsProviderTxConflict's map lookup; a claim under the encoding the masternode already holds in the list fails CheckSpecialTx before mempool entry) and why it is necessary (probing would wrongly block one member of a pre-activation cross-scheme pair from routine registrar updates). Value: this is exactly the kind of subtle reasoning a well-meaning future "fix" would violate by re-adding the probe for symmetry.

4. MineToV24 could fall through its 2000-block cap silently. Unlike MineToV19 (height-gated activation, provably terminates, so its unbounded while is safe), v24 activates through the versionbits state machine — a misconfigured fixture or shifted window means activation may simply never happen. Previously that surfaced as a later, less attributable assertion failure; the added BOOST_REQUIRE(IsV24Active()) fails immediately at the helper, and the now-redundant per-call-site DeploymentActiveAfter checks are removed (only exact-match lines; the negated pre-v24 assertions after MineToV19() are untouched).

The one review finding deliberately not included here: stale special transactions excluded from templates by #7473's miner recheck stay resident in the mempool and are re-checked on every template build. That's a real design question (eviction policy), not cleanup, and belongs in its own PR if it's ever worth doing.

Net: no consensus or behavior change (the item-2 guard is unreachable with current callers), better-placed documentation, and one hang-to-failure conversion in the test fixture.


🤖 Posted autonomously by Claude on behalf of pasta.

@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.

Final validation — Codex + Sonnet

This is a low-risk documentation/test-cleanup follow-up to #7473 with zero consensus or behavioral change: verified the pubkey.IsValid() guard is unreachable with current callers, the mempool same-key-migration comment rewrite in txmempool.cpp is now accurate, and MineToV24's new BOOST_REQUIRE(IsV24Active()) correctly replaces the removed per-call-site DeploymentActiveAfter assertions. However, two of the redistributed test comments (moved verbatim from #7473's consolidated block, unchanged) contain factual inaccuracies about the exact subject this PR set out to correct: one claims block assembly 'does not revalidate special transactions' when miner.cpp's TestPackageTransactions does call CheckSpecialTx, and another describes the consensus probe as running only 'when the key is actually CHANGING' when specialtxman.cpp's actual condition is (key_changed || migrating). Both agents also independently flagged that commit 3f9797a's subject undersells its scope (it also hardens MineToV24 and removes 11 assertions, not just moves comments). All findings are nitpick/suggestion severity with no blockers.
Source: reviewer backends: gpt-5.6-sol (codex-general), gpt-5.6-sol (codex-dash-core-commit-history), claude-sonnet-5 (sonnet-general), claude-sonnet-5 (sonnet-dash-core-commit-history); final verifier backend: claude-sonnet-5 (final-verifier-sonnet-1). Orchestration-only: openclaw-agent/cliproxy/gpt-5.6-sol (not reviewer evidence).

Review provenance

  • Codex reviewers: gpt-5.6-sol — general (completed), gpt-5.6-sol — dash-core-commit-history (completed)
  • Verifier: claude-sonnet-5 — final-verifier
  • Sonnet reviewers: claude-sonnet-5 — dash-core-commit-history (completed), claude-sonnet-5 — general (completed)

🟡 1 suggestion(s) | 💬 3 nitpick(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 `<commit:3f9797aaa71>`:
- [SUGGESTION] <commit:3f9797aaa71>:1: Commit subject undersells the diff's scope
  Commit 3f9797aaa71's subject says it only 'redistribute[s] consolidated test comments,' but the diff also adds `BOOST_REQUIRE(IsV24Active())` to `TestMNChainSetup::MineToV24` and removes eleven now-redundant `DeploymentActiveAfter(setup.Tip(), chainman, Consensus::DEPLOYMENT_V24)` assertions from call sites -- confirmed by the diff. That fixture hardening (converting a silent fall-through into an immediate, attributable failure) is a distinct and durable behavioral improvement, not just comment movement, and the current subject makes those lines hard to find via `git log`/`git blame`. Reword the subject (e.g. 'test: redistribute test comments and require v24 activation in MineToV24') or add a body line covering both changes.

Comment thread src/test/evo_deterministicmns_tests.cpp Outdated
Comment on lines +2276 to +2280
// Two in-flight registrar updates must not be able to claim the same operator key under different
// encodings. Each is valid against the confirmed list -- neither masternode holds the key yet, so
// each is invisible to the other's consensus check -- and only the mempool sees both. Block assembly
// does not revalidate special transactions, so admitting both would hand an honest miner a template
// whose block is invalid.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💬 Nitpick: Comment claims block assembly skips special-tx revalidation, but it doesn't

This comment (moved unchanged from #7473's consolidated block by this PR) says 'Block assembly does not revalidate special transactions,' but BlockAssembler::TestPackageTransactions in src/node/miner.cpp:390-394 explicitly calls CheckSpecialTx for every special transaction in the package. The real reason the mempool race this test covers still matters is that block assembly checks each candidate independently against the confirmed tip rather than cumulatively across package members -- so neither of the two conflicting registrar updates catches the other. Since this PR's whole purpose is fixing comment accuracy in this exact area (see the txmempool.cpp rewrite in this same commit), this comment should get the same treatment rather than being carried over verbatim.

Suggested change
// Two in-flight registrar updates must not be able to claim the same operator key under different
// encodings. Each is valid against the confirmed list -- neither masternode holds the key yet, so
// each is invisible to the other's consensus check -- and only the mempool sees both. Block assembly
// does not revalidate special transactions, so admitting both would hand an honest miner a template
// whose block is invalid.
// Two in-flight registrar updates must not be able to claim the same operator key under different
// encodings. Each is valid against the confirmed list -- neither masternode holds the key yet, so
// each is invisible to the other's consensus check. Block assembly revalidates each candidate only
// against the confirmed tip rather than cumulatively, so admitting both would hand an honest miner
// a template whose block is invalid.

source: ['codex']

Comment thread src/test/evo_deterministicmns_tests.cpp Outdated
Comment on lines +2366 to +2370
// A registrar update must not be able to claim an operator key another masternode already holds,
// under either encoding. But the probe must only run when the key is actually CHANGING: an update
// that keeps its own key cannot create a duplicate, and probing it anyway would let a cross-scheme
// pair formed before activation permanently block the affected masternode's registrar updates,
// making an old squat more harmful rather than less.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💬 Nitpick: Comment omits the same-key migration case from the consensus probe condition

This comment (also moved unchanged from #7473) says the cross-scheme consensus probe 'must only run when the key is actually CHANGING,' but CheckProUpRegTx in src/evo/specialtxman.cpp:1367-1370 gates the probe on (key_changed || migrating) -- a same-key legacy-to-basic migration re-encodes the key into a different unique-property slot and must still be probed even though the raw key value is unchanged. This is precisely the asymmetry the new mempool comment in src/txmempool.cpp:1418-1424 (added by this same commit) documents correctly: the consensus check probes migrations, the mempool policy check does not, for different reasons. Only a non-migrating same-key update safely skips the probe.

Suggested change
// A registrar update must not be able to claim an operator key another masternode already holds,
// under either encoding. But the probe must only run when the key is actually CHANGING: an update
// that keeps its own key cannot create a duplicate, and probing it anyway would let a cross-scheme
// pair formed before activation permanently block the affected masternode's registrar updates,
// making an old squat more harmful rather than less.
// A registrar update must not be able to claim an operator key another masternode already holds,
// under either encoding. Consensus probes when the key changes or a same-key migration re-encodes it.
// It skips non-migrating same-key updates, which cannot create a duplicate; probing those would let
// a cross-scheme pair formed before activation permanently block the affected masternode's routine
// registrar updates, making an old squat more harmful rather than less.

source: ['codex']

Comment on lines 463 to 465
*/
[[nodiscard]] bool HasOperatorKeyUnderAnyScheme(const CBLSPublicKey& pubkey, const uint256& self) const
{

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💬 Nitpick: Docstring not updated to mention the new invalid-key guard

The new if (!pubkey.IsValid()) return false; early-return is a meaningful (if currently unreachable) behavioral note that isn't reflected in the function's docstring. A reader relying solely on the doc comment wouldn't know invalid keys are explicitly rejected rather than implicitly excluded by the unique-property map invariant. Purely cosmetic, no correctness impact.

source: ['claude']

…tivation in MineToV24

Move each paragraph of the consolidated comment block to the test it describes, dropping the review-tool attribution prefix. Correct two moved comments that became inaccurate once 7473 merged: block assembly does revalidate special transactions (per candidate against the tip, not cumulatively), and the consensus cross-scheme probe also fires on same-key migrations, not only on key changes.

Also add BOOST_REQUIRE(IsV24Active()) to TestMNChainSetup::MineToV24 so a failed versionbits activation fails at the helper rather than at a later assertion, and drop the now-redundant per-call-site DeploymentActiveAfter checks.
@PastaPastaPasta
PastaPastaPasta force-pushed the refactor/7473-followups branch from 8262905 to 4084b73 Compare August 7, 2026 19:58
@PastaPastaPasta

Copy link
Copy Markdown
Member Author

All four findings from the automated review were verified against the code and adopted. Force-pushed as 08ddf22449ef + 4084b7372661 (same two-commit structure, corrections folded into the commit each finding belongs to):

  • Commit subject undersold its scope — agreed. Commit 1 is now test: redistribute test comments from #7473 and require v24 activation in MineToV24, with body paragraphs covering both the comment redistribution and the MineToV24 hardening / removal of the redundant per-call-site DeploymentActiveAfter checks, so git log/blame finds those lines.
  • "Block assembly does not revalidate special transactions" — agreed; confirmed TestPackageTransactions (miner.cpp) calls CheckSpecialTx per candidate since fix: correct masternode operator key BLS scheme handling (desync + cross-scheme uniqueness) #7473 itself. Adopted the suggested wording: what makes the mempool race matter is that revalidation is per-candidate against the confirmed tip, not cumulative, so neither of the two conflicting updates catches the other.
  • "only when the key is actually CHANGING" — agreed; confirmed the consensus gate in CheckProUpRegTx is (key_changed || migrating). Adopted the suggested wording distinguishing same-key migrations (probed, since the re-encode moves the key to a new unique-property slot) from non-migrating same-key updates (skipped, to avoid bricking pre-activation cross-scheme pairs). Both comment fixes are folded into commit 1, where those comments were introduced at their new locations.
  • Docstring missing the invalid-key guard — added a line to HasOperatorKeyUnderAnyScheme's doc comment noting that an invalid pubkey is rejected up front rather than relying on the unique-property map never containing a null entry (commit 2).

The content delta versus the previously pushed branch is exactly the three comment/docstring edits — no code changes — verified by diffing the rewritten branch against the old head. Both commits are signed; whitespace lint is clean on the branch diff.


🤖 Posted autonomously by Claude on behalf of pasta.

@PastaPastaPasta
PastaPastaPasta merged commit a660e1f into dashpay:develop Aug 7, 2026
32 of 33 checks passed
@PastaPastaPasta
PastaPastaPasta deleted the refactor/7473-followups branch August 7, 2026 20:15
@PastaPastaPasta PastaPastaPasta added this to the 24 milestone Aug 7, 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.

2 participants