Skip to content

fix(key-wallet): prune observed spends during the initial sync - #1014

Open
ZocoLini wants to merge 2 commits into
devfrom
fix/prune-observed-spends-during-sync
Open

ZocoLini wants to merge 2 commits into
devfrom
fix/prune-observed-spends-during-sync

Conversation

@ZocoLini

@ZocoLini ZocoLini commented Sep 12, 2026

Copy link
Copy Markdown
Collaborator

observed_spent_outpoints records every input of every transaction in every block the wallet processes, false positives included, and is pruned only up to a chainlock the wallet has applied. The client defers chainlocks until SyncComplete, so nothing is pruned during an initial sync. On a mainnet restore of the bench wallet the map reached 1 487 967 entries (every input of 10 295 blocks, 505 946 transactions), above the 1 000 000 entries the serde adapter accepts on load, so a wallet persisted mid-sync could not be loaded back.

The dispatcher still defers applying chainlocks, but now passes the deferred chainlock's height on through note_chain_lock_height. The wallet uses it only as a finality boundary for pruning: entries at or below min(synced_height, highest chainlock applied or noted) are evicted. As before, only chain-locked spends are forgotten, and no record is promoted.

Pruning mid-sync opened one path: redelivering a funding transaction whose output sits in spent_before_funded, after its observed-spend entry was evicted, re-inserted the spent coin into utxos. update_utxos now keeps such an output held; the new test fails without that guard.

Validated with 5 consecutive mainnet restores at 100 Mbit / 100 ms

Closes #899

`observed_spent_outpoints` records every input of every transaction in every
block the wallet processes, false positives included, and is pruned only up to
a chainlock the wallet has applied. The client defers chainlocks until
`SyncComplete`, so nothing is pruned during an initial sync. On a mainnet
restore of the bench wallet the map reached 1 487 967 entries (every input of
10 295 blocks, 505 946 transactions), above the 1 000 000 entries the serde
adapter accepts on load, so a wallet persisted mid-sync could not be loaded
back.

The dispatcher still defers applying chainlocks, but now passes the deferred
chainlock's height on through `note_chain_lock_height`. The wallet uses it
only as a finality boundary for pruning: entries at or below
min(synced_height, highest chainlock applied or noted) are evicted. As before,
only chain-locked spends are forgotten, and no record is promoted.

Pruning mid-sync opened one path: redelivering a funding transaction whose
output sits in `spent_before_funded`, after its observed-spend entry was
evicted, re-inserted the spent coin into `utxos`. `update_utxos` now keeps such
an output held; the new test fails without that guard.

Validated with 5 consecutive mainnet restores at 100 Mbit / 100 ms, all ending
at 7112 records, 14 114 383 sat and 13 389 addresses. Peak RSS was 1378–1724
MiB against 1488 MiB before, within run-to-run spread.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017DruChNTWXwJoWPartZwCf
@coderabbitai

coderabbitai Bot commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

Next included review available in 59 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: b112a612-bbfd-480e-ad6c-85137dc73b46

📥 Commits

Reviewing files that changed from the base of the PR and between 350f5f7 and 026fba0.

📒 Files selected for processing (7)
  • dash-spv/src/client/event_handler.rs
  • key-wallet-manager/src/process_block.rs
  • key-wallet-manager/src/wallet_interface.rs
  • key-wallet/src/managed_account/managed_core_funds_account.rs
  • key-wallet/src/tests/observed_spent_outpoints_tests.rs
  • key-wallet/src/wallet/managed_wallet_info/mod.rs
  • key-wallet/src/wallet/managed_wallet_info/wallet_info_interface.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

❌ Patch coverage is 63.63636% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 77.20%. Comparing base (350f5f7) to head (026fba0).

Files with missing lines Patch % Lines
key-wallet-manager/src/process_block.rs 0.00% 5 Missing ⚠️
key-wallet-manager/src/wallet_interface.rs 0.00% 1 Missing ⚠️
key-wallet/src/wallet/managed_wallet_info/mod.rs 83.33% 1 Missing ⚠️
...allet/managed_wallet_info/wallet_info_interface.rs 85.71% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##              dev    #1014      +/-   ##
==========================================
- Coverage   77.23%   77.20%   -0.04%     
==========================================
  Files         329      329              
  Lines       83862    83880      +18     
==========================================
- Hits        64768    64756      -12     
- Misses      19094    19124      +30     
Flag Coverage Δ
core 78.24% <ø> (ø)
ffi 50.94% <ø> (ø)
rpc 20.00% <ø> (ø)
spv 92.06% <100.00%> (-0.11%) ⬇️
wallet 79.77% <61.90%> (-0.02%) ⬇️
Files with missing lines Coverage Δ
dash-spv/src/client/event_handler.rs 93.75% <100.00%> (-0.27%) ⬇️
.../src/managed_account/managed_core_funds_account.rs 87.56% <100.00%> (+0.01%) ⬆️
key-wallet-manager/src/wallet_interface.rs 9.09% <0.00%> (-0.29%) ⬇️
key-wallet/src/wallet/managed_wallet_info/mod.rs 74.24% <83.33%> (+0.01%) ⬆️
...allet/managed_wallet_info/wallet_info_interface.rs 80.82% <85.71%> (+0.12%) ⬆️
key-wallet-manager/src/process_block.rs 92.24% <0.00%> (-0.91%) ⬇️

... and 4 files with indirect coverage changes

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017DruChNTWXwJoWPartZwCf
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.

key-wallet: observed_spent_outpoints grows unpruned for the whole initial sync

1 participant