Skip to content

feat(dash-spv)!: validate header difficulty against Dark Gravity Wave - #1161

Open
ZocoLini wants to merge 2 commits into
devfrom
feat/validate-header-difficulty
Open

ZocoLini wants to merge 2 commits into
devfrom
feat/validate-header-difficulty

Conversation

@ZocoLini

@ZocoLini ZocoLini commented Oct 12, 2026 •

Copy link
Copy Markdown
Collaborator

Closes #1116.

Headers were only checked against the target in their own bits, so past the last checkpoint a peer could serve a chain of minimal difficulty (and, through fork detection, make the client drop stored blocks, #1103).

  • Params::next_work_required(window, last_height, time): the bits Dash Core requires, as its GetNextWorkRequired from Dark Gravity Wave on, including testnet's min difficulty rules and regtest's fixed limit. None on devnets (whose difficulty rules are set per devnet), before DGW, or without 24 headers of history.
  • BlockHeaderValidator::new(network, ancestors, tip_height): each header's bits must match, checked in the same parallel pass as continuity and PoW. BlockHeadersManager passes the last 24 stored headers, so both initial sync and announced headers are checked. The first headers after a checkpoint start, without full history, are not.
  • New ValidationError::InvalidDifficulty.
  • Header::mainnet_fixture() in dashcore test utils: 30 real mainnet headers (1999976 to 2000005), hashes checked.

Tests: next_work_required reproduces the bits of mainnet header 2000000 and applies the devnet, pre-DGW, regtest and testnet rules; the validator rejects a header whose hash meets an easier target but not the required difficulty.

Breaking: BlockHeadersManager::new takes the network, and BlockHeaderValidator::new takes the network, the stored headers the batch extends and the height of the last of them.

🤖 Generated with Claude Code

PR Hygiene · 6383467

  • Bots — coderabbitai skipped after its own rate limit
  • Self-review — address xdustinface requested changes, then post /self-reviewed
  • Build green
  • Approvals
    • dash-spv (dash-spv/src/client/lifecycle.rs, dash-spv/src/error.rs, dash-spv/src/sync/block_headers/manager.rs and 1 more) — QuantumExplorer or xdustinface
    • files with no dedicated owner (dash/src/consensus/params.rs, dash/src/pow.rs, dash/src/test_utils/block.rs and 1 more) — QuantumExplorer or xdustinface

When every merge requirement is met, the PR Hygiene check passes. Reviewer limits do not block merging; other required GitHub checks and protections still apply.

@coderabbitai

coderabbitai Bot commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 9 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Repository: dashpay/rust-dashcore/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 5cbcf052-3263-4a04-8c00-c1c6ab06cef9
📥 Commits

Reviewing files that changed from the base of the PR and between 80298d0 and 6383467.

📒 Files selected for processing: 8
  • dash-spv/src/client/lifecycle.rs
  • dash-spv/src/error.rs
  • dash-spv/src/sync/block_headers/manager.rs
  • dash-spv/src/validation/header.rs
  • dash/src/consensus/params.rs
  • dash/src/pow.rs
  • dash/src/test_utils/block.rs
  • dash/tests/data/mainnet_headers_1999976.txt
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@codecov

codecov Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.00000% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 79.07%. Comparing base (80298d0) to head (6383467).
⚠️ Report is 12 commits behind head on dev.

Files with missing lines Patch % Lines
dash/src/pow.rs 96.55% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##              dev    #1161      +/-   ##
==========================================
+ Coverage   78.87%   79.07%   +0.20%     
==========================================
  Files         304      304              
  Lines       81405    81527     +122     
==========================================
+ Hits        64206    64467     +261     
+ Misses      17199    17060     -139     
Flag Coverage Δ
core 77.67% <96.55%> (+0.08%) ⬆️
ffi 52.03% <ø> (+1.24%) ⬆️
rpc 52.05% <ø> (ø)
spv 92.81% <100.00%> (+0.03%) ⬆️
wallet 82.19% <ø> (ø)
Files with missing lines Coverage Δ
dash-spv/src/client/lifecycle.rs 91.40% <100.00%> (+0.10%) ⬆️
dash-spv/src/error.rs 33.33% <ø> (ø)
dash-spv/src/sync/block_headers/manager.rs 93.68% <100.00%> (+0.21%) ⬆️
dash-spv/src/validation/header.rs 98.05% <100.00%> (+0.87%) ⬆️
dash/src/consensus/params.rs 76.92% <ø> (ø)
dash/src/pow.rs 80.62% <96.55%> (+4.69%) ⬆️

... and 29 files with indirect coverage changes

@ZocoLini
ZocoLini force-pushed the feat/consensus-params branch from 55520e6 to 930a451 Compare October 13, 2026 14:50
@github-actions github-actions Bot added the merge-conflict The PR conflicts with the target branch. label Oct 13, 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.

@ZocoLini
ZocoLini force-pushed the feat/consensus-params branch from 930a451 to 21e6cf5 Compare October 13, 2026 15:03
@ZocoLini
ZocoLini force-pushed the feat/validate-header-difficulty branch from 8da4424 to 321d486 Compare October 13, 2026 17:50
@github-actions github-actions Bot removed the merge-conflict The PR conflicts with the target branch. label Oct 13, 2026
Base automatically changed from feat/consensus-params to dev October 14, 2026 07:17
@github-actions github-actions Bot added the merge-conflict The PR conflicts with the target branch. label Oct 14, 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.

Headers were only checked against the target in their own bits, so past
the last checkpoint a peer could serve a chain of minimal difficulty.
Params::next_work_required computes the bits Dash Core requires, as its
GetNextWorkRequired from Dark Gravity Wave on, and the header validator
rejects a header whose bits differ, from the stored headers before it.

Closes #1116

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ZocoLini
ZocoLini force-pushed the feat/validate-header-difficulty branch from 321d486 to 03e740e Compare October 15, 2026 17:51
@ZocoLini
ZocoLini marked this pull request as ready for review October 15, 2026 17:51
@github-actions

github-actions Bot commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Waiting for bot review — coderabbitai not yet. Wait for the missing reviews, or a writer can post /skip-bots to proceed without them; blocking findings still need addressing.
Full checklist in the description.

@github-actions github-actions Bot added waiting-bots Waiting for the review bots to report on this head and removed merge-conflict The PR conflicts with the target branch. labels Oct 15, 2026
@github-actions

github-actions Bot commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Bots are done — your move: address xdustinface requested changes, then post /self-reviewed.
Full checklist in the description.

@github-actions github-actions Bot added waiting-self-review Waiting for the author to post /self-reviewed bot-review-skipped A required review bot did not report; it was skipped by the window or by a person. and removed waiting-bots Waiting for the review bots to report on this head labels Oct 15, 2026
@ZocoLini

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@ZocoLini
ZocoLini requested a review from xdustinface October 16, 2026 12:34
@coderabbitai

coderabbitai Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor
⚠️ Action not completed

Review rate limited.

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.

@xdustinface xdustinface left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

  1. Mainnet below 68589 needs the 50% tolerance. Core only requires exact bits above 68589 (validation.cpp, ContextualCheckBlockHeader). Below that it allows 50%, because early mainnet ran DGW v1/v2. Real headers from 34140 to 68588 fail the exact check. Real mainnet sync with this branch: --start-height 0 rejects 34140 (bits 0x1c00f8a9, required 0x1c00f987) and --start-height 50000 rejects 50024. Skip the check, or use the 50% tolerance, on mainnet up to 68589, and add a test at that boundary.

  2. Checkpoint 750000 has the wrong time and bits. It has 1491953700 / 0x1a075a02, but the real block has 1507424630 / 0x1a027884. The hash is correct. Since the anchor now feeds DGW, real mainnet sync with --start-height 750000 rejects 750024 (bits 0x1a02b0d8, required 0x1a08c176). Every wallet born in 750000..799999 hits this. Please fix the entry and add a test that checks every checkpoint's time and bits against the real block.

    In all three runs the client then reports headers Synced at the stall height (32000, 50000, 750000) and never moves again (#1194). The same runs on the base commit sync through.

  3. The first 23 headers after the start checkpoint are unchecked, and they seed DGW for everything after. A wallet born after the last checkpoint (2500000) starts there, so a peer can serve 23 minimum-difficulty headers and stay at minimum difficulty from then on. That is the #1116 attack. Either close the gap (for example, start one checkpoint earlier so those headers are pinned by a hash) or change Closes #1116 to Part of #1116 and open a follow-up.

@ZocoLini

Copy link
Copy Markdown
Collaborator Author

@xdustinface what if a finish #375 first, that would solve the point 2 issue

Early mainnet ran the first versions of Dark Gravity Wave, so Dash Core
only requires the exact bits above height 68589. Up to it, the bits only
have to be within 50% of the required difficulty. The header validator
now applies the same rule, so real mainnet headers from 34140 to 68588
are accepted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ZocoLini

Copy link
Copy Markdown
Collaborator Author

Also, #375 could store the previous 23, so a checkpoint is now a Vec o headers, and not only one, and, when geenrating the checkpoints, I would be able to validate the chainn in that point

@github-actions

github-actions Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Waiting for bot review — coderabbitai not yet. Wait for the missing reviews, or a writer can post /skip-bots to proceed without them; blocking findings still need addressing.
Full checklist in the description.

@github-actions github-actions Bot added waiting-bots Waiting for the review bots to report on this head and removed waiting-self-review Waiting for the author to post /self-reviewed bot-review-skipped A required review bot did not report; it was skipped by the window or by a person. labels Oct 19, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Bots are done — your move: address xdustinface requested changes, then post /self-reviewed.
Full checklist in the description.

@github-actions github-actions Bot added waiting-self-review Waiting for the author to post /self-reviewed bot-review-skipped A required review bot did not report; it was skipped by the window or by a person. and removed waiting-bots Waiting for the review bots to report on this head labels Oct 19, 2026
@github-actions github-actions Bot added the merge-conflict The PR conflicts with the target branch. label Oct 22, 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

bot-review-skipped A required review bot did not report; it was skipped by the window or by a person. merge-conflict The PR conflicts with the target branch. waiting-self-review Waiting for the author to post /self-reviewed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

dash-spv: validate header difficulty against the network-required target

2 participants