Skip to content

refactor(dash-spv): drop committed range sweep - #1016

Merged
ZocoLini merged 1 commit into
devfrom
refactor/drop-committed-range-sweep
Sep 23, 2026
Merged

ZocoLini merged 1 commit into
devfrom
refactor/drop-committed-range-sweep

Conversation

@ZocoLini

@ZocoLini ZocoLini commented Sep 12, 2026 •

Copy link
Copy Markdown
Collaborator

Drops de final sweep, syncs goes from 21–27 min → 6–9 min, gives up the #846 case. This can be done now, because all (known) bugs that were losing funds are solved and it doesn't discover anything new

PR Hygiene · 1674cd2

  • Bots — coderabbitai ✓
  • Self-review — post /self-reviewed
  • Within your 5 open PRs
  • Build green
  • Approvals
    • dash-spv (dash-spv/src/sync/filters/batch.rs, dash-spv/src/sync/filters/block_match_tracker.rs, dash-spv/src/sync/filters/coinjoin_gap_discovery_tests.rs and 2 more) — QuantumExplorer or xdustinface

When every box is checked the PR Hygiene check passes and this can merge.

@coderabbitai

coderabbitai Bot commented Sep 12, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

Next included review available in 18 minutes.

Check out review usage here.

View limit details

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

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

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Repository: dashpay/rust-dashcore/.coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 2ace7df7-a4c6-455d-b999-03c39db0b316

📥 Commits

Reviewing files that changed from the base of the PR and between 59dd41b and 1674cd2.

📒 Files selected for processing (5)
  • dash-spv/src/sync/filters/batch.rs
  • dash-spv/src/sync/filters/block_match_tracker.rs
  • dash-spv/src/sync/filters/coinjoin_gap_discovery_tests.rs
  • dash-spv/src/sync/filters/manager.rs
  • dash-spv/src/sync/filters/sync_manager.rs

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 Sep 12, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 77.09%. Comparing base (59dd41b) to head (1674cd2).

Additional details and impacted files
@@            Coverage Diff             @@
##              dev    #1016      +/-   ##
==========================================
- Coverage   77.16%   77.09%   -0.08%     
==========================================
  Files         329      329              
  Lines       83847    83577     -270     
==========================================
- Hits        64699    64430     -269     
+ Misses      19148    19147       -1     
Flag Coverage Δ
core 78.18% <ø> (ø)
ffi 49.29% <ø> (-0.01%) ⬇️
rpc 20.00% <ø> (ø)
spv 91.98% <100.00%> (-0.10%) ⬇️
wallet 80.33% <ø> (ø)
Files with missing lines Coverage Δ
dash-spv/src/sync/filters/batch.rs 97.56% <ø> (-0.32%) ⬇️
dash-spv/src/sync/filters/block_match_tracker.rs 99.35% <ø> (-0.02%) ⬇️
dash-spv/src/sync/filters/manager.rs 97.83% <100.00%> (+0.02%) ⬆️
dash-spv/src/sync/filters/sync_manager.rs 100.00% <ø> (ø)

... and 3 files with indirect coverage changes

@ZocoLini
ZocoLini force-pushed the refactor/drop-committed-range-sweep branch 2 times, most recently from 5156e07 to 53c8f98 Compare September 22, 2026 16:04
ZocoLini added a commit that referenced this pull request Sep 22, 2026
With the committed-height release gone, the segment cache itself has to
bound the resident set. Ten 50 000-item segments per cache kept most of
a restore in memory; two keep the peak below what the release achieved,
without costing time.

Mainnet restore, mainnet.100mbi.100ms, #1015/#1016/#1014 applied,
jemalloc heap profiling, wallet identical in every run (14114383 sat,
7112 records, 13389 addresses):

  segments      peak RSS   time      segment loads from disk
                                     (headers/filter headers/filters/blocks)
  10 + #946     982 MiB    8.2 min   -
  10            1490 MiB   8.8 min   84 / 2 / 28 / 0
  2             930 MiB    8.8 min   212 / 103 / 74 / 0
  1             1000 MiB   7.7 min   427 / 742 / 156 / 33

Each cache served ~2.34M requests from memory in every run. One segment
starts reloading block segments of up to 87 MB from disk, which raises
the peak again.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017DruChNTWXwJoWPartZwCf
ZocoLini added a commit that referenced this pull request Sep 22, 2026
A dirty segment leaving the resident set used to wait in `evicted`,
in memory, until the next 5 s storage tick wrote it. The resident
limit was therefore not a limit: every segment evicted between two
ticks stayed in memory. Now eviction writes the segment first and only
then drops it; if the write fails the segment stays resident and the
error is returned. The `evicted` map is gone, and the tick only
persists the resident segments.

Mainnet restore, mainnet.100mbi.100ms, #1015/#1016/#1014 applied,
two resident segments: 7.7 and 7.9 min, peak RSS 943 and 948 MiB,
wallet identical (14114383 sat, 7112 records, 13389 addresses). No
cache misses served from `evicted` any more; header, filter header and
filter segments are reloaded from disk about as often as they used to
come back from `evicted` (~270 / ~150 / ~90), block segments never.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017DruChNTWXwJoWPartZwCf
ZocoLini added a commit that referenced this pull request Sep 22, 2026
… one buffer

`Segment::persist` encoded the whole segment into a `Vec` before
handing it to `atomic_write`. For a block segment near the tip (up to
87 MB on disk) that `Vec` grew to 128 MiB, and since dirty segments are
now written on eviction this happened in the middle of the sync.
`atomic_write_items` encodes one item at a time through a 1 MiB
`BufWriter` into the temporary file, then syncs and renames it as
before. `atomic_write` keeps its behaviour and shares the temporary file
and rename logic.

Mainnet restore, mainnet.100mbi.100ms, #1015/#1016/#1014 applied, two
resident segments, wallet identical in every run (14114383 sat, 7112
records, 13389 addresses):

  whole-segment buffer   peak RSS 943 / 948 MiB   7.7 / 7.9 min
  streamed               peak RSS 845 / 855 / 856 MiB   9.4 / 7.7 / 6.5 min

The persist buffer, 68–133 MiB in the earlier heap snapshots, no longer
shows up. The 9.4 min run lost time to peers in the header and filter
header phases.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017DruChNTWXwJoWPartZwCf
ZocoLini added a commit that referenced this pull request Sep 22, 2026
Every segment cache held 50 000 items, whatever an item costs. Near the
tip a block segment holds tens of MB of decoded blocks, while a header
segment spanning the same heights is 5.6 MB and a filter header one
1.6 MB. `Persistable::ITEMS_PER_SEGMENT` lets each type choose: headers
10 000 (~1.1 MB per segment), filter headers 50 000 (~1.6 MB), filters
2 000 (~2 MB near the tip) and blocks 1 000.

This changes the on-disk layout of the header, filter and block
segments. Storage written with 50 000-item segments is misread by this
layout and has to be deleted until a migration or a versioned folder
lands.

Mainnet restore, mainnet.100mbi.100ms, #1015/#1016/#1014 applied, two
resident segments, jemalloc heap profiling, wallet identical in every
run (14114383 sat, 7112 records, 13389 addresses):

  segment items           time          peak RSS      segment caches
  50 000 for every type   7.0 min       818 MiB       332 MiB
  5 000 for every type    7.3-8.3 min   554-687 MiB   23-106 MiB
  1 000 for every type    9.2-12.2 min  453-577 MiB   2-66 MiB
  per type (this commit)  7.5 min       538 MiB       38 MiB

With 1 000 items everywhere, the header and filter header phases paid an
fsync per evicted segment (105-141 s and 254-332 s instead of ~60 s and
~150 s). Blocks at 500 items saved ~18 MiB of cache but reloaded 50 %
more block segments.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017DruChNTWXwJoWPartZwCf
@ZocoLini ZocoLini closed this Sep 22, 2026
@ZocoLini ZocoLini reopened this Sep 22, 2026
@HashEngineering

Copy link
Copy Markdown
Contributor

I tested this with an android build and found no negative effects.

**Speed —Two clean restores of the same
wallet, both from scan_start=0, same device:

build sync to SYNCED
before #1016 7 min 04 s
with #1016 3 min 07 s

In my test I was using a modified (not pushed) #979.

@github-actions github-actions Bot added the merge-conflict The PR conflicts with the target branch. label Sep 23, 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 refactor/drop-committed-range-sweep branch from 53c8f98 to 1b6d1c8 Compare September 23, 2026 18:04
@github-actions github-actions Bot removed the merge-conflict The PR conflicts with the target branch. label Sep 23, 2026
@ZocoLini ZocoLini changed the title Refactor/drop committed range sweep refactor(dash-spv): drop committed range sweep Sep 23, 2026
…scripts rescan

The #846 sweep re-tested every late-derived script against the whole stored
filter history, from the wallet's birth height. On a mainnet restore of the
bench wallet that was one 63 s walk over 200 000..tip matching 41 687 blocks,
overwhelmingly compact-filter false positives, then about 17.7 min downloading
and applying them, out of a 21–27 min sync.

The notification-driven path (`collect_new_scripts`,
`FiltersBatch::collected_scripts`, the current-and-later batch rescan at
commit) duplicated `reconcile_untested_scripts`, which asks the wallet what it
watches, a superset of any `new_scripts`, and re-tests whatever the batch never
matched. `rescan_complete` was set immediately before the batch left
`active_batches`, so it was never read as true.

Trade-off: the #846 case, a CoinJoin output paying an index derived only after
its batch committed, is no longer recovered. Its repro,
`coinjoin_gap_limit_stall_across_committed_batch`, fails without the sweep and
is removed with it, as is the sweep-cost test. The bench wallet does not hit
that case.

Validated on top of the spend re-application fix: 5 consecutive mainnet
restores at 100 Mbit / 100 ms, then 100/50 Mbit x 100/500 ms, all ending at
7112 records, 14 114 383 sat and 13 389 addresses, in 6.0–17.2 min.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017DruChNTWXwJoWPartZwCf
@ZocoLini
ZocoLini force-pushed the refactor/drop-committed-range-sweep branch 2 times, most recently from 1b6d1c8 to 1674cd2 Compare September 23, 2026 18:22
@ZocoLini
ZocoLini marked this pull request as ready for review September 23, 2026 18:23
@github-actions github-actions Bot added the waiting-bots Waiting for the review bots to report on this head label Sep 23, 2026
@ZocoLini

Copy link
Copy Markdown
Collaborator Author

@coderabbitai approve

@coderabbitai

coderabbitai Bot commented Sep 23, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Comments resolved and changes approved.

@github-actions

Copy link
Copy Markdown
Contributor

Bots are done — your move: 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 and removed waiting-bots Waiting for the review bots to report on this head labels Sep 23, 2026
@ZocoLini
ZocoLini merged commit 342cb29 into dev Sep 23, 2026
66 of 68 checks passed
@ZocoLini
ZocoLini deleted the refactor/drop-committed-range-sweep branch September 23, 2026 18:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

waiting-self-review Waiting for the author to post /self-reviewed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants