fix(key-wallet): stop pruning spent CoinJoin addresses from the filter scan - #985
Open
ZocoLini wants to merge 1 commit into
Open
fix(key-wallet): stop pruning spent CoinJoin addresses from the filter scan#985ZocoLini wants to merge 1 commit into
ZocoLini wants to merge 1 commit into
Conversation
Contributor
|
Warning Review limit reachedNext included review available in 11 minutes. View limit detailsLimit 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. Review configuration: ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (9)
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. Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## dev #985 +/- ##
==========================================
+ Coverage 77.14% 77.15% +0.01%
==========================================
Files 329 329
Lines 82998 83031 +33
==========================================
+ Hits 64026 64060 +34
+ Misses 18972 18971 -1
|
ZocoLini
force-pushed
the
fix/coinjoin-scan-keeps-spent-addresses
branch
2 times, most recently
from
August 27, 2026 12:02
aa2b6fb to
d52b0f1
Compare
…r scan The forward compact-filter query dropped a CoinJoin address once it was used and held no unspent output, on the grounds that CoinJoin addresses are single-use by protocol, so nothing would ever pay one again. Mainnet does not honour that. On a restore of a mixing-heavy wallet, 287 CoinJoin addresses were paid by more than one transaction — verified on the scriptPubKey, not on a derivation label — some of them nearly 100 000 blocks after being emptied. Eight of those fell in a window where the wallet had already stopped watching them, and the scan never saw the payments: 9 transactions missed between heights 2 170 285 and 2 170 440 5 outputs never recorded (80 000 sat) 9 spends never recorded (176 780 sat) 4 already-spent outputs left on the books as spendable balance overstated by 96 780 sat Reproduced identically across four full syncs and by two independent methods (an A/B diff of per-address dumps, and an end-of-sync re-match of the whole chain against still-unspent scripts, which named the same heights and the same addresses without being told what to look for). The saving did not pay for that either. Pruning shrinks the query sixfold at the tip (13 378 to 2 200 scripts), but over a full mainnet restore it moves the sync by 7.7% in blocks and 2.3% in time — inside the run-to-run spread, with the fastest of the four runs being an unpruned one. So the mechanism goes rather than being switched off. ManagedWalletInfo no longer overrides scan_script_pubkeys, and ManagedCoreFundsAccount::unspent_or_unused_script_pubkeys goes with it, having had no other caller. The seam in the trait stays, documented with why the scan watches every CoinJoin address however long ago it was emptied. One test covers it, replacing the four that asserted set membership at two layers and now would only be checking that a defaulted method calls the one it delegates to. It pays a CoinJoin address, spends the output, then builds a real BIP158 filter over the block carrying a second payment and requires the scan query to match — and fails if the pruning comes back. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015NhHBDGiKfiGpy7FwooyfS
ZocoLini
force-pushed
the
fix/coinjoin-scan-keeps-spent-addresses
branch
from
August 27, 2026 12:42
d52b0f1 to
a1d383d
Compare
ZocoLini
marked this pull request as ready for review
August 27, 2026 12:45
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
#949 dropped a CoinJoin address from the forward compact-filter query once it was used and held no unspent output, on the grounds that CoinJoin addresses are single-use by protocol, so nothing would ever pay one again.
Mainnet does not honour that. On a restore of a mixing-heavy wallet, 287 CoinJoin addresses were paid by more than one transaction, some of them nearly 100 000 blocks after being emptied. Eight of those fell in a window where the wallet had already stopped watching them, and the scan never saw the payments:
9 transactions missed between heights 2 170 285 and 2 170 440
5 outputs never recorded (80 000 sat)
9 spends never recorded (176 780 sat)
4 already-spent outputs left on the books as spendable
balance overstated by 96 780 sat
I looked for options to kept CoinJoin addresses collection as small as possible but the bug can use any address at any point, so all of them have to be tracked. I was also reported that the bug is still present