-
Notifications
You must be signed in to change notification settings - Fork 38.6k
wallet: generate random change target for each tx for better privacy #24494
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
f4a6fe0 to
6d803e5
Compare
|
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. |
6d803e5 to
a653b84
Compare
|
Ok fixed the wallet_bumpfee.py break. |
|
cc @xekyo |
a653b84 to
6490a74
Compare
S3RK
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Concept ACK.
I'm somewhat concerned though that testing coin selection behavior becomes more difficult because one can't predictably explore edge cases now. We can either rely on a more complex stochastic testing or add a way to fix the change traget (though I'm not a fan of adding functionality just for the tests). How should we think about the trade off between increasing test complexity vs increasing code complexity for testability?
I'd argue that if we're testing coin selection specifically (i.e. calling something like |
6490a74 to
3173930
Compare
|
Set SRD change target to |
promag
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Concept ACK.
3173930 to
53a30b5
Compare
|
Added release notes, docs for |
|
The code changes look fine but I would like to run a simulation first to see how it affects our coin selection strategies. |
53a30b5 to
dee7186
Compare
|
Concept ACK, but I'm wondering how making the @achow101: Very curious for your simulation results, and it might be interesting to also run a variant where SRD and Knapsack use the same |
murchandamus
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks very good, thanks for taking this up so quickly.
src/wallet/coinselection.cpp
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
0a25b209b2fab44d639b93f9699e1364f270527e: Perhaps mention here how the nTargetValue is composed, it would be nice to get a reminder here whether it already includes min_change or does not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
src/wallet/coinselection.cpp
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not clear to me what we are trying to achieve in the context of smaller payments here. The proposed range for the change amount would cause the payment to always be smaller than the change which clearly identifies their roles (if one of the outputs is below 25,000, the smaller is the payment). It may be better to avoid making a tiny change output here, if there is no privacy benefit. Perhaps it would be better to drop the special case and then just go with CHANGE_LOWER?
Alternatively, we should perhaps make the lower bound for change always smaller than the payment to ensure that the roles are unclear.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to CHANGE_LOWER when the payment amount is less than 25k
src/wallet/coinselection.h
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a bit worried that "change_target" may be understood here as us actually trying to produce change with exactly that amount, while that would just reflect the behavior of the Knapsack algorithm. Perhaps it would be clearer to identify the "target change" as a form of minimum change here. To a lesser degree this concern also applies to the comments on the static boundaries in lines 20 and 22.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to min_change_target everywhere. The comment above the member should hopefully be pretty clear.
src/qt/coincontroldialog.cpp
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not your fault obviously, but this comment is kinda confusing where it's at and would fit much better around line 493. Since you're touching this section already, could you perhaps move it down?
|
Simulation results:
|
5988dd1 to
e75c8dd
Compare
|
Rebased + addressed @MarcoFalke's comments |
murchandamus
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK e75c8dd14d0988c1bf4594105de905c2c444b530
no behavior changes, since the target is always MIN_CHANGE
If the wallet always chooses 1 million sats as its change target, it is easier to fingerprint transactions created by the Core wallet.
e75c8dd to
9053f64
Compare
|
Rebased for #24091. The CI failure is the "AssertionError: Fee of 0.00003160 BTC too high!" error from wallet_send.py, unrelated |
|
ACK 9053f64 |
murchandamus
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reACK 9053f64
|
The pull request description is outdated/wrong. The correct description can be found in the docstring of |
Updated. In the spirit of keeping pull documentation correct, tbh this pull didn't really randomize change targets. I accidentally created 2 separate change target params instead of renaming when updating from dee7186 to 57c035b. Thanks @S3RK for catching this and pointing it out to me, it's since been fixed in #25825. |
A new feature was added to bitcoind 24.1+ that tries to make the change output indistinguishable from the payment output. This is a great for privacy, but it adds randomness to coin selection and uses a non-minimal set of inputs sometimes. We work around this by updating the amount of the output we want bitcoind to use to make sure it's sufficient to pay for both the channel funding and the change output. This shouldn't be too much of an issue for normal operation, where we'll sometimes use two inputs instead of one, which costs more fees, but increases privacy. See bitcoin/bitcoin#24494 for details.
Closes #24458 - Knapsack always chooses 1 million sats as its change target, making it easier to fingerprint transactions created by the Core wallet. Instead of using a fixed value, choose one randomly each time (within a range).
GenerateChangeTargetworks as follows:The SRD target is 50ksat, not randomized, since the selection does not aim for a specific target anyway.
(Note the random change target was mistakenly not used yet in this PR, see #25825).