Skip to content

fix: reduce GETBLOCKTXN disk read lock scope#7350

Open
thepastaclaw wants to merge 1 commit into
dashpay:developfrom
thepastaclaw:fix/getblocktxn-recent-disk-read
Open

fix: reduce GETBLOCKTXN disk read lock scope#7350
thepastaclaw wants to merge 1 commit into
dashpay:developfrom
thepastaclaw:fix/getblocktxn-recent-disk-read

Conversation

@thepastaclaw

Copy link
Copy Markdown

fix: reduce GETBLOCKTXN disk read lock scope

Issue being fixed or feature implemented

Recent GETBLOCKTXN handling selected and read the requested block from disk while
holding cs_main. A peer can request recent block transactions repeatedly, so the
disk I/O should not extend the validation/global chain lock hold time.

What was done?

  • Capture the recent block's disk position while holding cs_main.
  • Release cs_main before reading the block from disk.
  • Verify the read block hash still matches the requested block hash before
    sending BLOCKTXN.
  • Treat a missing, pruned, or mismatched read defensively by logging and
    returning instead of asserting.

How Has This Been Tested?

Tested on macOS arm64.

  • git diff --check upstream/develop...HEAD
  • ./configure --without-gui --disable-bench --disable-fuzz-binary
    with the macOS arm64 depends config.site
  • make -j8 src/dashd
  • Pre-PR code review gate: ship

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

@thepastaclaw

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

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.

@coderabbitai

coderabbitai Bot commented Jun 9, 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

Run ID: 0278137c-db57-4d3a-994d-e0899bf9a9a9

📥 Commits

Reviewing files that changed from the base of the PR and between 6440dea and 97af883.

📒 Files selected for processing (1)
  • src/net_processing.cpp

Walkthrough

This PR hardens GETBLOCKTXN message handling in the Dash peer-to-peer network layer. A compile-time assertion now enforces that the maximum block transaction depth does not exceed the minimum blocks retained. The serving logic for deep blocks has been refactored to capture the disk position from the block index, explicitly read the block from disk at that position, and verify the retrieved block's hash before responding, replacing an earlier approach that relied on assertions for success validation.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Suggested reviewers

  • UdjinM6
  • bigwalter1979-cloud
🚥 Pre-merge checks | ✅ 4 | ❌ 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 (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: reducing the lock scope for disk reads in GETBLOCKTXN handling, which is the core objective of this PR.
Description check ✅ Passed The description comprehensively explains the issue being fixed, changes implemented, testing performed, and breaking changes, all clearly related to the changeset.
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.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Infer (1.2.0)
src/net_processing.cpp

src/net_processing.cpp:6:10: error: 'net_processing.h' file not found with include; use "quotes" instead
6 | #include <net_processing.h>
| ^~~~~~~~~~~~~~~~~~
| "net_processing.h"
In file included from src/net_processing.cpp:6:
src/net_processing.h:9:10: error: 'net.h' file not found with include; use "quotes" instead
9 | #include <net.h>
| ^~~~~~~
| "net.h"
In file included from src/net_processing.cpp:6:
In file included from src/net_processing.h:9:
src/net.h:9:10: error: 'bip324.h' file not found with include; use "quotes" instead
9 | #include <bip324.h>
| ^~~~~~~~~~
| "bip324.h"
In file included from src/net_processing.cpp:6:
In file included from src/net_processing.h:9:
In file included from src/net.h:9:
src/bip324.h:12:10: error: 'crypto/chacha20.h' file not found with include; use "quotes" instead
12 | #include <crypto/chacha20.h>
|

... [truncated 2200 characters] ...

__CTrans.CTrans_funct.get_clang_stmt_trans in file "src/clang/cTrans.ml" (inlined), line 5395, characters 4-69
Called from ClangFrontend__CTrans.CTrans_funct.get_custom_stmt_trans in file "src/clang/cTrans.ml", line 5401, characters 8-55
Called from ClangFrontend__CTrans.CTrans_funct.exec_trans_instrs.exec_trans_instrs_rev in file "src/clang/cTrans.ml" (inlined), line 5365, characters 28-54
Called from ClangFrontend__CTrans.CTrans_funct.exec_trans_instrs in file "src/clang/cTrans.ml" (inlined), line 5389, characters 6-70
Called from ClangFrontend__CTrans.CTrans_funct.instructions_trans in file "src/clang/cTrans.ml", line 5451, characters 25-68
Called from ClangFrontend__CFrontend_decl.CFrontend_decl_funct.add_method.f in file "src/clang/cFrontend_decl.ml", line 48, characters 12-91
Called


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.

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown

✅ No Merge Conflicts Detected

This PR currently has no conflicts with other open PRs.

@thepastaclaw thepastaclaw force-pushed the fix/getblocktxn-recent-disk-read branch from 6440dea to 97af883 Compare June 9, 2026 02:38
@thepastaclaw

thepastaclaw commented Jun 9, 2026

Copy link
Copy Markdown
Author

✅ Review complete (commit 97af883)

@thepastaclaw thepastaclaw marked this pull request as ready for review June 9, 2026 04:52

@thepastaclaw thepastaclaw left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Code Review

Targeted change narrows the cs_main hold window in GETBLOCKTXN by capturing the block file position under the lock and performing the disk read outside it, with a hash check that fails closed on stale/pruned/mismatched reads. Both agents concur the change is correct; only a minor log-granularity nitpick remains.

💬 1 nitpick(s)

Comment thread src/net_processing.cpp
Comment on lines +4523 to 4525
if (!hash || *hash != req.blockhash) {
LogPrint(BCLog::NET, "Peer %d sent us a getblocktxn for a block we could not read\n", pfrom.GetId());
return;

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

💬 Nitpick: Log message conflates I/O failure with hash mismatch

After dropping cs_main, the failure path emits the same "a block we could not read" line for two distinct conditions: ReadBlockFromDisk returning nullopt (open/deserialize/PoW failure) and the read succeeding with *hash != req.blockhash (a stale FlatFilePos / disk-state inconsistency after the lock was released). Distinguishing these helps operators tell transient I/O or pruning issues from a position-vs-hash race. Diagnostic quality only; not a defect.

source: ['claude']

@PastaPastaPasta

Copy link
Copy Markdown
Member

Is this not code we inherited from bitcoin? it is rare we want to accept a "fix" in their code.

@thepastaclaw

Copy link
Copy Markdown
Author

Good question. I checked this against upstream Bitcoin: the change is actually bringing this path back in line with the current inherited Bitcoin pattern, not inventing a Dash-only behavior.

Bitcoin master already copies the recent block position under cs_main, releases the lock, then reads the block from disk outside cs_main and serves BLOCKTXN. This PR does the same for Dash, with the Dash-local ReadBlockFromDisk API/hash check shape.

So I agree with the general rule — we should be cautious about “fixing” inherited Bitcoin code — but in this case the safer path is to follow the upstream Bitcoin fix rather than keep Dash on the older wider-lock version.

@PastaPastaPasta

Copy link
Copy Markdown
Member

@thepastaclaw

Bitcoin master already copies the recent block position under cs_main, releases the lock, then reads the block from disk outside cs_main and serves BLOCKTXN. This PR does the same for Dash, with the Dash-local ReadBlockFromDisk API/hash check shape.

Hmm; it seems then, that there may be a backport that we should backport instead of doing this adhoc?

@thepastaclaw

Copy link
Copy Markdown
Author

Yep — I traced it more precisely and there is an exact upstream Bitcoin commit for this:

That commit adds the same MAX_BLOCKTXN_DEPTH <= MIN_BLOCKS_TO_KEEP assertion and moves the GETBLOCKTXN disk read out from under cs_main. This PR is effectively that backport adapted to Dash's current ReadBlockFromDisk shape / block hash validation.

So I agree with your process concern: this should be treated as a Bitcoin backport, not as an ad-hoc Dash-only fix. If you prefer, I can close this PR and re-run it through the normal backport flow; otherwise I can update the PR metadata/commit message to explicitly cite the upstream commit.

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