Skip to content

Conversation

@UdjinM6
Copy link

@UdjinM6 UdjinM6 commented Nov 20, 2025

Issue being fixed or feature implemented

Previously, evodb_verify_or_repair_impl held cs_main for the entire operation, which could take minutes when verifying/repairing large block ranges. This caused significant lock contention and blocked other operations requiring cs_main.

This commit reduces the cs_main lock scope to only the initial setup phase where we resolve block indexes from the active chain. The actual verification and repair work (applying diffs, rebuilding lists from blocks, verifying snapshots) now runs without holding cs_main.

What was done?

Changes:

  • Wrap block index resolution in a scoped cs_main lock
  • Remove AssertLockHeld(cs_main) from helper functions:
    • RecalculateAndRepairDiffs
    • CollectSnapshotBlocks
    • VerifySnapshotPair
    • RepairSnapshotPair
    • RebuildListFromBlock (CSpecialTxProcessor)
  • Update function signatures to remove EXCLUSIVE_LOCKS_REQUIRED(cs_main)

How Has This Been Tested?

Run evodb verify/repair on a mainnet node and monitor logs - it keeps processing other stuff while rpc command is still running.

Breaking Changes

This is safe because:

  • CBlockIndex pointers remain valid after lock release (never deleted)
  • Block parent relationships (pprev, GetAncestor) are immutable
  • ReadBlockFromDisk takes cs_main internally when accessing nFile/nDataPos
  • Helper functions only process already-loaded block data and snapshots
  • ChainLocks prevent deep reorgs in Dash anyway

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 (for repository code-owners and collaborators only)

Previously, evodb_verify_or_repair_impl held cs_main for the entire
operation, which could take minutes when verifying/repairing large block
ranges. This caused significant lock contention and blocked other
operations requiring cs_main.

This commit reduces the cs_main lock scope to only the initial setup
phase where we resolve block indexes from the active chain. The actual
verification and repair work (applying diffs, rebuilding lists from
blocks, verifying snapshots) now runs without holding cs_main.

Changes:
- Wrap block index resolution in a scoped cs_main lock
- Remove AssertLockHeld(cs_main) from helper functions:
  * RecalculateAndRepairDiffs
  * CollectSnapshotBlocks
  * VerifySnapshotPair
  * RepairSnapshotPair
  * RebuildListFromBlock (CSpecialTxProcessor)
- Update function signatures to remove EXCLUSIVE_LOCKS_REQUIRED(cs_main)

This is safe because:
- CBlockIndex pointers remain valid after lock release (never deleted)
- Block parent relationships (pprev, GetAncestor) are immutable
- ReadBlockFromDisk takes cs_main internally when accessing nFile/nDataPos
- Helper functions only process already-loaded block data and snapshots
- ChainLocks prevent deep reorgs in Dash anyway
@UdjinM6 UdjinM6 added this to the 23.0.1 milestone Nov 20, 2025
@github-actions
Copy link

github-actions bot commented Nov 20, 2025

✅ No Merge Conflicts Detected

This PR currently has no conflicts with other open PRs.

@coderabbitai
Copy link

coderabbitai bot commented Nov 20, 2025

Walkthrough

This pull request relaxes or removes cs_main lock assertions and thread-safety annotations in evo codepaths. Several CDeterministicMNManager methods (RecalculateAndRepairDiffs, CollectSnapshotBlocks, VerifySnapshotPair, RepairSnapshotPair) have had ::cs_main requirements removed from their declarations and internal assertions. CSpecialTxProcessor::RebuildListFromBlock also has its EXCLUSIVE_LOCKS_REQUIRED(cs_main) annotation and an internal cs_main assertion removed. A new method MigrateLegacyDiffs(const CBlockIndex* const tip_index) with EXCLUSIVE_LOCKS_REQUIRED(!cs, ::cs_main) was added. In the RPC layer, cs_main scoping was narrowed during block resolution and the callback used for list building was switched to RebuildListFromBlock (renamed from BuildNewListFromBlock). No functional logic changes beyond locking preconditions are introduced.

Sequence Diagram(s)

No sequence diagram included — the changes are restricted to synchronization contract/annotation adjustments rather than new control-flow paths.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Areas requiring extra attention:

  • Verify all callers satisfy the new lock preconditions for:
    • RecalculateAndRepairDiffs (now EXCLUSIVE_LOCKS_REQUIRED(!cs))
    • CollectSnapshotBlocks, VerifySnapshotPair, RepairSnapshotPair (no longer require ::cs_main)
    • RebuildListFromBlock (no longer requires cs_main)
  • Audit removed runtime assertions (cs_main) to ensure callers provide equivalent synchronization where needed.
  • Inspect the new MigrateLegacyDiffs declaration and its intended callers/usage for correct locking.
  • Confirm the narrowed cs_main scope in RPC block resolution does not open race windows between resolution and subsequent operations.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: reducing cs_main lock scope in evodb verify/repair operations, which is the primary focus of all modifications across the affected files.
Description check ✅ Passed The description is directly related to the changeset, explaining the performance issue being addressed, detailing what changes were made, and providing justification for why the changes are safe.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ce506bc and 084bb62.

📒 Files selected for processing (2)
  • src/evo/deterministicmns.h (2 hunks)
  • src/evo/specialtxman.h (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: kwvg
Repo: dashpay/dash PR: 6543
File: src/wallet/receive.cpp:240-251
Timestamp: 2025-02-06T14:34:30.466Z
Learning: Pull request #6543 is focused on move-only changes and refactoring, specifically backporting from Bitcoin. Behavior changes should be proposed in separate PRs.
Learnt from: knst
Repo: dashpay/dash PR: 6692
File: src/llmq/blockprocessor.cpp:217-224
Timestamp: 2025-08-19T14:57:31.801Z
Learning: In PR #6692, knst acknowledged a null pointer dereference issue in ProcessBlock() method where LookupBlockIndex may return nullptr but is passed to gsl::not_null, and created follow-up PR #6789 to address it, consistent with avoiding scope creep in performance-focused PRs.
Learnt from: UdjinM6
Repo: dashpay/dash PR: 6786
File: ci/test/04_install.sh:99-101
Timestamp: 2025-08-01T07:46:37.840Z
Learning: In backport PRs like #6786, UdjinM6 prefers to defer non-critical fixes (such as shell command expansion issues) to separate commits/PRs to maintain focus on the primary backport objectives, consistent with the project's pattern of avoiding scope creep.
Learnt from: kwvg
Repo: dashpay/dash PR: 6761
File: src/chainlock/signing.cpp:247-250
Timestamp: 2025-07-29T14:32:48.369Z
Learning: In PR #6761, kwvg acknowledged a null pointer check issue in ChainLockSigner::Cleanup() method but deferred it to follow-up, consistent with the pattern of avoiding scope creep in refactoring PRs.
Learnt from: knst
Repo: dashpay/dash PR: 6511
File: src/evo/deterministicmns.cpp:1369-1373
Timestamp: 2025-01-07T18:50:44.838Z
Learning: The functions `MigrateDBIfNeeded` and `MigrateDBIfNeeded2` in `src/evo/deterministicmns.cpp` are temporary and will be removed in a future version. Refactoring suggestions for these functions should be avoided.
Learnt from: kwvg
Repo: dashpay/dash PR: 6718
File: test/functional/test_framework/test_framework.py:2102-2102
Timestamp: 2025-06-09T16:43:20.996Z
Learning: In the test framework consolidation PR (#6718), user kwvg prefers to limit functional changes to those directly related to MasternodeInfo, avoiding scope creep even for minor improvements like error handling consistency.
📚 Learning: 2025-11-13T20:02:55.480Z
Learnt from: UdjinM6
Repo: dashpay/dash PR: 6969
File: src/evo/deterministicmns.h:441-479
Timestamp: 2025-11-13T20:02:55.480Z
Learning: In `src/evo/deterministicmns.h`, the `internalId` field in `CDeterministicMN` and the `mnInternalIdMap` in `CDeterministicMNList` are non-deterministic and used only for internal bookkeeping and efficient lookups. Different nodes can assign different internalIds to the same masternode depending on their sync history. Methods like `IsEqual()` intentionally ignore internalId mappings and only compare consensus-critical deterministic fields (proTxHash, collateral, state, etc.).

Applied to files:

  • src/evo/specialtxman.h
  • src/evo/deterministicmns.h
📚 Learning: 2025-01-07T18:50:44.838Z
Learnt from: knst
Repo: dashpay/dash PR: 6511
File: src/evo/deterministicmns.cpp:1369-1373
Timestamp: 2025-01-07T18:50:44.838Z
Learning: The functions `MigrateDBIfNeeded` and `MigrateDBIfNeeded2` in `src/evo/deterministicmns.cpp` are temporary and will be removed in a future version. Refactoring suggestions for these functions should be avoided.

Applied to files:

  • src/evo/deterministicmns.h
🧬 Code graph analysis (1)
src/evo/deterministicmns.h (2)
src/validation.cpp (1)
  • ChainstateManager (6051-6061)
src/instantsend/signing.h (1)
  • Consensus (16-18)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: x86_64-pc-linux-gnu / Build depends
  • GitHub Check: x86_64-w64-mingw32 / Build depends
  • GitHub Check: x86_64-apple-darwin / Build depends
  • GitHub Check: x86_64-pc-linux-gnu_nowallet / Build depends
  • GitHub Check: x86_64-pc-linux-gnu_multiprocess / Build depends
  • GitHub Check: arm-linux-gnueabihf / Build depends
  • GitHub Check: Lint / Run linters
🔇 Additional comments (3)
src/evo/deterministicmns.h (2)

743-747: Lock contract correctly implemented: RecalculateAndRepairDiffs safely runs heavy work without cs_main

Verification confirms the refactoring is sound:

  • Call site (evo.cpp:1767–1799): LOCK(::cs_main) is scoped and released before line 1815 invokes RecalculateAndRepairDiffs, so the caller obeys the !cs contract.
  • Implementation (deterministicmns.cpp:1585–1700): Only performs read-only access to m_evoDb, read-only access to const CBlockIndex pointers, and calls internal helpers. No lock acquisition or cs_main assumption.
  • Lock annotation correctly reflects the change: EXCLUSIVE_LOCKS_REQUIRED(!cs) alone, removing the former cs_main dependency, allowing the heavy verify/repair work to run concurrently without blocking the global chainstate lock.

Helper methods (CollectSnapshotBlocks, VerifySnapshotPair, RepairSnapshotPair) are internal and inherit the parent method's lock contract safely.


758-765: Snapshot helpers verified as lock-agnostic with no external cache dependencies

Verification confirms the refactored signatures and implementations are sound:

  • CollectSnapshotBlocks: Pure block index navigation, no manager state access
  • VerifySnapshotPair: Reads diffs from m_evoDb only (line 1760), no cache access
  • RepairSnapshotPair: Disk-based block reading and list building, no cache access
  • WriteRepairedDiffs: Properly holds lock before clearing caches (lines 1900–1903), with EXCLUSIVE_LOCKS_REQUIRED(!cs) enforcing the lock policy

All three helpers work exclusively with materialized snapshots and block index pointers, never touching mnListsCache or mnListDiffsCache without holding cs.

src/evo/specialtxman.h (1)

85-87: RebuildListFromBlock removal of cs_main requirement is correct and properly implemented

Verification confirms the change is sound:

  • Implementation (lines 183-283+ in specialtxman.cpp) contains no AssertLockHeld(cs_main) and uses only lock-free operations: CCoinsViewCache reads, DeploymentActiveAfter on consensus parameters, and local list mutations.

  • RPC call site (evodb verify/repair at line 1815) releases cs_main before calling RecalculateAndRepairDiffs, which is declared with EXCLUSIVE_LOCKS_REQUIRED(!cs) to explicitly reflect that it does not require the global lock. The scoped LOCK(::cs_main) ends at line 1807, well before the callback is invoked.

  • Normal validation path (line 180 in specialtxman.cpp) calls RebuildListFromBlock from a different overload that has AssertLockHeld(cs_main), so that call site remains protected.

The header annotation change aligns the declaration with actual requirements, enabling minutes-long evodb verify/repair operations without blocking the main lock.

Tip

📝 Customizable high-level summaries are now available in beta!

You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.

  • Provide your own instructions using the high_level_summary_instructions setting.
  • Format the summary however you like (bullet lists, tables, multi-section layouts, contributor stats, etc.).
  • Use high_level_summary_in_walkthrough to move the summary from the description to the walkthrough section.

Example instruction:

"Divide the high-level summary into five sections:

  1. 📝 Description — Summarize the main change in 50–60 words, explaining what was done.
  2. 📓 References — List relevant issues, discussions, documentation, or related PRs.
  3. 📦 Dependencies & Requirements — Mention any new/updated dependencies, environment variable changes, or configuration updates.
  4. 📊 Contributor Summary — Include a Markdown table showing contributions:
    | Contributor | Lines Added | Lines Removed | Files Changed |
  5. ✔️ Additional Notes — Add any extra reviewer context.
    Keep each section concise (under 200 words) and use bullet or numbered lists for clarity."

Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later.


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.

Copy link
Collaborator

@kwvg kwvg left a comment

Choose a reason for hiding this comment

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

utACK 084bb62

Copy link
Collaborator

@knst knst left a comment

Choose a reason for hiding this comment

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

utACK 084bb62

@PastaPastaPasta PastaPastaPasta merged commit a3118c1 into dashpay:develop Nov 21, 2025
32 of 35 checks passed
PastaPastaPasta added a commit to PastaPastaPasta/dash that referenced this pull request Dec 1, 2025
…epair operations

084bb62 chore: clang-format (UdjinM6)
ce506bc perf: reduce cs_main lock scope in evodb verify/repair operations (UdjinM6)

Pull request description:

  ## Issue being fixed or feature implemented
  Previously, evodb_verify_or_repair_impl held cs_main for the entire operation, which could take minutes when verifying/repairing large block ranges. This caused significant lock contention and blocked other operations requiring cs_main.

  This commit reduces the cs_main lock scope to only the initial setup phase where we resolve block indexes from the active chain. The actual verification and repair work (applying diffs, rebuilding lists from blocks, verifying snapshots) now runs without holding cs_main.

  ## What was done?
  Changes:
  - Wrap block index resolution in a scoped cs_main lock
  - Remove AssertLockHeld(cs_main) from helper functions:
    * RecalculateAndRepairDiffs
    * CollectSnapshotBlocks
    * VerifySnapshotPair
    * RepairSnapshotPair
    * RebuildListFromBlock (CSpecialTxProcessor)
  - Update function signatures to remove EXCLUSIVE_LOCKS_REQUIRED(cs_main)

  ## How Has This Been Tested?
  Run evodb verify/repair on a mainnet node and monitor logs - it keeps processing other stuff while rpc command is still running.

  ## Breaking Changes
  This is safe because:
  - CBlockIndex pointers remain valid after lock release (never deleted)
  - Block parent relationships (pprev, GetAncestor) are immutable
  - ReadBlockFromDisk takes cs_main internally when accessing nFile/nDataPos
  - Helper functions only process already-loaded block data and snapshots
  - ChainLocks prevent deep reorgs in Dash anyway

  ## 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 _(for repository code-owners and collaborators only)_

ACKs for top commit:
  kwvg:
    utACK 084bb62
  knst:
    utACK 084bb62

Tree-SHA512: aa0db93133767cc6de897d2989c35f00d1cd0506c51463a86cb76cbbe51ea8be5372efb9dbc16791992d8128bc26812e075d13c30c396f97f22198e9611e75dc
PastaPastaPasta added a commit that referenced this pull request Dec 2, 2025
736bb26 chore: bump manpages for 23.0.1 (pasta)
d5c7d25 chore: bump nMinimumChainWork and defaultAssumeValid (pasta)
4f8aa71 chore: bump version to 23.0.1 (pasta)
0865b7c docs: add release notes for 23.0.1 (pasta)
2048b42 Merge #6986: test: new commandline argument -tinyblk to use blk size just 64kb instead 16Mb (pasta)
1a9b20c Merge #7013: fix: update BuildTestVectors call to adjust batch size based on output flag (pasta)
36e4679 Merge #7009: fix: include QDebug directly (pasta)
69d0c9c Merge #6999: feat: verify and repair evodb diffs automatically at node startup (pasta)
ca16437 Merge #6996: perf: reduce cs_main lock scope in evodb verify/repair operations (pasta)
207526e Merge #6977: fix: bls benchmarks crash when ran independently (pasta)
226aaf4 Merge #6969: feat: add evodb verify and repair RPC commands (pasta)
92abe9b Merge #6964: perf: remove duplicated check of same key in the instant send database (pasta)
5a1ec4c Merge #6961: fix: correct BLS scheme setting in `MigrateLegacyDiffs()` when `nVersion` is present (pasta)
bf653d3 Merge #6949: depends: Qt 5.15.18 (pasta)
faf58cd merge bitcoin#30774: Qt 5.15.16 (Kittywhiskers Van Gogh)
6a995f5 Merge #6944: fix: HD chain encryption check ordering issue (pasta)

Pull request description:

  ## Issue being fixed or feature implemented
  See commits; release v23.0.1

  ## What was done?
  see commits

  ## How Has This Been Tested?

  ## Breaking Changes

  ## Checklist:
    _Go over all the following points, and put an `x` in all the boxes that apply._
  - [ ] 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
  - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_

ACKs for top commit:
  kwvg:
    utACK 736bb26

Tree-SHA512: fe02c4c3e520b11af54d09c47bda94112313456f9f1cb6d14e78ef16704b2a8ec8feb80fa914c55e152db2bcac7f278291824aaa36c8079eb9e0c9bff9e554a4
PastaPastaPasta added a commit that referenced this pull request Dec 4, 2025
fe1cff3 chore: bump release to 23.0.2 (pasta)
a8f15c1 Merge #7032: fix: drop gsl usage from RebuildListFromBlock function wrapper (pasta)
736bb26 chore: bump manpages for 23.0.1 (pasta)
d5c7d25 chore: bump nMinimumChainWork and defaultAssumeValid (pasta)
4f8aa71 chore: bump version to 23.0.1 (pasta)
0865b7c docs: add release notes for 23.0.1 (pasta)
2048b42 Merge #6986: test: new commandline argument -tinyblk to use blk size just 64kb instead 16Mb (pasta)
1a9b20c Merge #7013: fix: update BuildTestVectors call to adjust batch size based on output flag (pasta)
36e4679 Merge #7009: fix: include QDebug directly (pasta)
69d0c9c Merge #6999: feat: verify and repair evodb diffs automatically at node startup (pasta)
ca16437 Merge #6996: perf: reduce cs_main lock scope in evodb verify/repair operations (pasta)
207526e Merge #6977: fix: bls benchmarks crash when ran independently (pasta)
226aaf4 Merge #6969: feat: add evodb verify and repair RPC commands (pasta)
92abe9b Merge #6964: perf: remove duplicated check of same key in the instant send database (pasta)
5a1ec4c Merge #6961: fix: correct BLS scheme setting in `MigrateLegacyDiffs()` when `nVersion` is present (pasta)
bf653d3 Merge #6949: depends: Qt 5.15.18 (pasta)
faf58cd merge bitcoin#30774: Qt 5.15.16 (Kittywhiskers Van Gogh)
6a995f5 Merge #6944: fix: HD chain encryption check ordering issue (pasta)
6fd7059 chore: mark v23 as release (pasta)
ae08f53 docs: integrate 6946 release notes into final (pasta)
74a222d Merge #6946: feat: show seed on wallet creation (pasta)
877343a Merge #6943: fix: don't treat arrays/objects as string literals for composite methods (pasta)
00368fb Merge #6940: fix: reuse best clsig to avoid potential race condition (pasta)
8eceb98 Merge #6938: fix: logic error in `CheckDecryptionKey` (pasta)
3f30664 Merge #6929: fix: repair `makeseeds.py`, `getblockchaininfo[softforks]` help text, drop extra `generate`s from test, resolve macOS GID issue (pasta)
7ba4f1c Merge #6928: docs: update man pages for 23.0 (pasta)
a6c1d6a Merge #6920: chore: update minimum chain work, tx stats, checkpoints, seeds and SECURITY.md for v23 (pasta)
84df1f0 Merge #6909: chore: Translations 2025-10 (pasta)
a6449b1 Merge #6885: fix: improve governance/proposal dialog strings (pasta)
ebf3a64 docs: typos (pasta)
4ad5533 docs: typos (pasta)
f407453 doc: Replace Bitcoin Core PR references with Dash Core backport PRs (pasta)
78d0725 docs: add note on proto bump and platformban p2p (pasta)
e0519c3 docs: fix whitespace errors (pasta)
bc8db22 docs: minor improvements to release notes (pasta)
c338511 docs: reorganize rpc updates to organize extended address changes (thephez)
700c46e style: make heading style consistent (thephez)
bd636bd docs: add contributors (pasta)
6d29bc3 docs: revert changes deferred to v24 (pasta)
615f5ff docs: make the downgrade warning more confident (pasta)
567771a Apply suggestions from code review (PastaPastaPasta)
2b3211a docs: add link to 22.1.3 release notes (pasta)
548a38a docs: remove individual release notes files (pasta)
e770c25 docs: add v23.0.0 release notes and archive v22.1.3 (pasta)

Pull request description:

  ## Issue being fixed or feature implemented
  Includes changes from 23.0.0 release too because we never merged it back.

  ## What was done?

  ## How Has This Been Tested?

  ## Breaking Changes

  ## 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 _(for repository code-owners and collaborators only)_

ACKs for top commit:
  PastaPastaPasta:
    utACK 491db4a
  kwvg:
    utACK 491db4a

Tree-SHA512: 61895cd1f9d01ac7be1d407afe1ddd24b98e8242cb03229ecd586a4d2d1c43dbc62c98da52a8c715b3a5943fb40e99b23251e691f778779af9d6da94392122a3
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.

4 participants