Skip to content

fix: skip collecting block txids during IBD to prevent unbounded memory growth#7208

Merged
PastaPastaPasta merged 1 commit intodashpay:developfrom
thepastaclaw:fix/chainlock-ibd-memory-growth
Mar 12, 2026
Merged

fix: skip collecting block txids during IBD to prevent unbounded memory growth#7208
PastaPastaPasta merged 1 commit intodashpay:developfrom
thepastaclaw:fix/chainlock-ibd-memory-growth

Conversation

@thepastaclaw
Copy link

Motivation

ChainLockSigner is registered as a CValidationInterface and receives BlockConnected events during initial block download. It stores all non-coinbase txids for every connected block in blockTxs, but Cleanup() skips pruning while !IsBlockchainSynced(). This causes blockTxs to grow with the entire chain's transaction IDs during IBD/reindex, leading to unbounded memory growth.

Since TrySignChainTip() already returns early when !IsBlockchainSynced(), the collected txids are never used during IBD — they just accumulate until sync completes.

Fix

Add the same !IsBlockchainSynced() guard to BlockConnected() that already exists in TrySignChainTip() and Cleanup(), skipping txid collection entirely during IBD.

Validation

  • Traced TrySignChainTip() — confirms it early-returns when not synced, so txids collected during IBD are never consumed
  • Traced Cleanup() — confirms it also early-returns when not synced, so no pruning happens during IBD
  • Traced GetBlockTxs() — has a fallback path that reads from disk when txids aren't in blockTxs, so post-sync tip signing still works for blocks connected during IBD
  • BlockDisconnected only handles reorgs (erases single entry), not bulk cleanup

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

…ounded memory growth

ChainLockSigner::BlockConnected unconditionally stores all non-coinbase
txids for every connected block, but Cleanup() skips pruning while
!IsBlockchainSynced(). This causes the blockTxs map to grow with the
entire chain's transaction IDs during initial block download or reindex.

Since TrySignChainTip() already returns early when !IsBlockchainSynced(),
the collected txids are never used during IBD. Add the same guard to
BlockConnected to prevent the unnecessary memory accumulation.
@thepastaclaw
Copy link
Author

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Mar 11, 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.

@github-actions
Copy link

✅ No Merge Conflicts Detected

This PR currently has no conflicts with other open PRs.

@PastaPastaPasta PastaPastaPasta requested review from UdjinM6 and knst March 11, 2026 20:53
@PastaPastaPasta PastaPastaPasta marked this pull request as ready for review March 11, 2026 20:56
@coderabbitai
Copy link

coderabbitai bot commented Mar 11, 2026

Walkthrough

A guard clause was added to the ChainLockSigner::BlockConnected function that checks if the blockchain is fully synchronized before proceeding with block processing. The change introduces an early return statement that prevents further execution until sync completion. No modifications were made to existing logic or error handling patterns.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description check ✅ Passed The description comprehensively explains the problem, the fix, and validation steps, all directly related to the changeset's purpose.
Title check ✅ Passed The title clearly describes the main change: adding an early exit guard to skip txid collection during IBD to prevent memory growth, which matches the changeset's core objective.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

@PastaPastaPasta PastaPastaPasta changed the title fix(chainlock): skip collecting block txids during IBD to prevent unbounded memory growth fix: skip collecting block txids during IBD to prevent unbounded memory growth Mar 11, 2026
@UdjinM6 UdjinM6 added this to the 23.1.2 milestone Mar 11, 2026
Copy link

@UdjinM6 UdjinM6 left a comment

Choose a reason for hiding this comment

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

utACK c3a552a

@PastaPastaPasta PastaPastaPasta merged commit e855ae3 into dashpay:develop Mar 12, 2026
44 of 46 checks passed
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.

LGTM c3a552a

thepastaclaw pushed a commit to thepastaclaw/dash that referenced this pull request Mar 12, 2026
…event unbounded memory growth

c3a552a fix(chainlock): skip collecting block txids during IBD to prevent unbounded memory growth (PastaClaw)

Pull request description:

  ## Motivation

  `ChainLockSigner` is registered as a `CValidationInterface` and receives `BlockConnected` events during initial block download. It stores all non-coinbase txids for every connected block in `blockTxs`, but `Cleanup()` skips pruning while `!IsBlockchainSynced()`. This causes `blockTxs` to grow with the entire chain's transaction IDs during IBD/reindex, leading to unbounded memory growth.

  Since `TrySignChainTip()` already returns early when `!IsBlockchainSynced()`, the collected txids are never used during IBD — they just accumulate until sync completes.

  ## Fix

  Add the same `!IsBlockchainSynced()` guard to `BlockConnected()` that already exists in `TrySignChainTip()` and `Cleanup()`, skipping txid collection entirely during IBD.

  ## Validation

  - Traced `TrySignChainTip()` — confirms it early-returns when not synced, so txids collected during IBD are never consumed
  - Traced `Cleanup()` — confirms it also early-returns when not synced, so no pruning happens during IBD
  - Traced `GetBlockTxs()` — has a fallback path that reads from disk when txids aren't in `blockTxs`, so post-sync tip signing still works for blocks connected during IBD
  - `BlockDisconnected` only handles reorgs (erases single entry), not bulk cleanup

  ## Checklist

  - [x] I have performed a self-review of my own code
  - [x] 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

ACKs for top commit:
  UdjinM6:
    utACK c3a552a

Tree-SHA512: d395d33ff8c9d4f2539b8ab3fb14adafc732ff7b3a5cccc83efa390615926ea920e7d50490080ace39812960f04439b4387784a0ffa1d7c12f1e69434b3f336c
thepastaclaw added a commit to thepastaclaw/dash that referenced this pull request Mar 12, 2026
- Bump version: 23.1.1 → 23.1.2 (configure.ac)
- Update flatpak metainfo with v23.1.2 release entry
- Update release notes: include all v23.1.1 notes plus dashpay#7208 and dashpay#7209
- Update set-of-changes comparison link
- Add PastaPastaPasta to credits

v23.1.1 was scrubbed; releasing as v23.1.2 instead.
thepastaclaw pushed a commit to thepastaclaw/dash that referenced this pull request Mar 14, 2026
…event unbounded memory growth

c3a552a fix(chainlock): skip collecting block txids during IBD to prevent unbounded memory growth (PastaClaw)

Pull request description:

  ## Motivation

  `ChainLockSigner` is registered as a `CValidationInterface` and receives `BlockConnected` events during initial block download. It stores all non-coinbase txids for every connected block in `blockTxs`, but `Cleanup()` skips pruning while `!IsBlockchainSynced()`. This causes `blockTxs` to grow with the entire chain's transaction IDs during IBD/reindex, leading to unbounded memory growth.

  Since `TrySignChainTip()` already returns early when `!IsBlockchainSynced()`, the collected txids are never used during IBD — they just accumulate until sync completes.

  ## Fix

  Add the same `!IsBlockchainSynced()` guard to `BlockConnected()` that already exists in `TrySignChainTip()` and `Cleanup()`, skipping txid collection entirely during IBD.

  ## Validation

  - Traced `TrySignChainTip()` — confirms it early-returns when not synced, so txids collected during IBD are never consumed
  - Traced `Cleanup()` — confirms it also early-returns when not synced, so no pruning happens during IBD
  - Traced `GetBlockTxs()` — has a fallback path that reads from disk when txids aren't in `blockTxs`, so post-sync tip signing still works for blocks connected during IBD
  - `BlockDisconnected` only handles reorgs (erases single entry), not bulk cleanup

  ## Checklist

  - [x] I have performed a self-review of my own code
  - [x] 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

ACKs for top commit:
  UdjinM6:
    utACK c3a552a

Tree-SHA512: d395d33ff8c9d4f2539b8ab3fb14adafc732ff7b3a5cccc83efa390615926ea920e7d50490080ace39812960f04439b4387784a0ffa1d7c12f1e69434b3f336c
PastaPastaPasta added a commit that referenced this pull request Mar 14, 2026
 into v23.1.x

da16809 docs: add #7221 and #7222 to v23.1.2 release notes (PastaClaw)
8a93926 Merge #7222: fix: properly skip evodb repair on reindex (pasta)
b74b549 Merge #7221: refactor: rename bitcoin-util manpage and test references to dash-util (pasta)
81464ac Merge #7211: fix: qt info tab layout (pasta)
7c27c2f Merge #7209: fix: serialize TrySignChainTip to prevent concurrent signing race (pasta)
81d5eb2 Merge #7208: fix: skip collecting block txids during IBD to prevent unbounded memory growth (pasta)

Pull request description:

  ## Backport

  Cherry-picks of #7208, #7209, #7211, #7221, and #7222 into `v23.1.x` for v23.1.2.

  ### Included

  - #7208 — `fix: skip collecting block txids during IBD to prevent unbounded memory growth`
  - #7209 — `fix: serialize TrySignChainTip to prevent concurrent signing race`
  - #7211 — `fix: qt info tab layout`
  - #7221 — `refactor: rename bitcoin-util manpage and test references to dash-util`
  - #7222 — `fix: properly skip evodb repair on reindex`

ACKs for top commit:
  UdjinM6:
    utACK da16809

Tree-SHA512: bbe74a62fd34bdcaece22100050072706774854db47d61af644700ca063e2a3cdfd474fa451681861bf1a6e91436ebd3715838640fc992fbba7c2b57b4f02760
PastaPastaPasta added a commit that referenced this pull request Mar 16, 2026
da16809 docs: add #7221 and #7222 to v23.1.2 release notes (PastaClaw)
8a93926 Merge #7222: fix: properly skip evodb repair on reindex (pasta)
b74b549 Merge #7221: refactor: rename bitcoin-util manpage and test references to dash-util (pasta)
81464ac Merge #7211: fix: qt info tab layout (pasta)
7c27c2f Merge #7209: fix: serialize TrySignChainTip to prevent concurrent signing race (pasta)
81d5eb2 Merge #7208: fix: skip collecting block txids during IBD to prevent unbounded memory growth (pasta)
d02243c ci: run check-skip on blacksmith with GitHub-hosted fallback (PastaClaw)
033b3fe chore: regenerate manpages for v23.1.2 (PastaClaw)
ff965b5 chore: v23.1.2 release preparation (PastaClaw)
8d5936d chore: add #7191 and #7193 to v23.1.1 release notes (PastaClaw)
9f3662b chore: v23.1.1 release preparation (PastaClaw)
5dbfa98 chore: v23.1.1 release preparation (PastaClaw)
240a95f Merge #7193: fix: reject identity elements in deserialization and key generation (pasta)
444cbf2 Merge #7191: fix(qt): reseat quorum labels when new types are inserted (pasta)
00f590d Merge #7180: qt: add Tahoe styled icons for macOS, runtime styling for each network type, update bundle icon, add mask-based tray icon, generation scripts (pasta)
60dda51 Merge #7176: perf: do linear lookup instead building 2 heavy Hash-Maps (pasta)
df1ca87 Merge #7159: feat(qt): UI refresh (5/n, add proposal information widget to information, donut chart for proposal allocation) (pasta)
9061ad0 Merge #7118: feat(qt): UI refresh (4/n, introduce distinct widgets for Dash-specific reporting in debug window) (pasta)
64cc4f2 Merge #7160: feat(interfaces): consolidate masternode counts into one struct, expose chainlock, instantsend, credit pool, quorum statistics (pasta)
5d28a69 Merge #7157: fix(qt): prevent banned masternodes from returning status=0 (pasta)
e0b7386 Merge #7146: feat(qt): introduce framework for sourcing and applying data, use for `{Masternode,Proposal}List`s (pasta)
8fd53cd Merge #7144: feat(qt): add support for reporting `OP_RETURN` payloads as Data Transactions (pasta)
cc6f0bb Merge #7154: fix: MN update notifications had old_list/new_list swapped (pasta)
33f0138 Merge #7145: fix(qt): move labelError styling from proposalcreate.ui into general.css (pasta)
1bdbde6 Merge #7148: feat(qt): persist filter preferences in masternode list (pasta)
96bb601 Merge #7147: fix(qt): prevent overview page font double scaling, recalculate minimum width correctly, `SERVICE` and `STATUS` sorting, fix common types filtering (pasta)
da1e336 build: expand minimum Darwin version to macOS 11 (Big Sur) (Kittywhiskers Van Gogh)

Pull request description:

  ## Issue being fixed or feature implemented
  Note: Skipping changes from #7149 which was for the v23.1.x only.

  ## 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:
  kwvg:
    utACK 36988f9

Tree-SHA512: f5bf8f0af11379bbcea606108ee90af08c16f588ebdbfac1fdd567adfcad14926b9c797c8fa6b398fb65fc3210c5f2c084015ea07718371df04e2412625f42d4
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