Use destination groups instead of coins in coin_select to improve privacy#1851
Use destination groups instead of coins in coin_select to improve privacy#1851martinsaposnic wants to merge 3 commits intobitcoindevkit:masterfrom
Conversation
5eddc55 to
15351ea
Compare
New flag called avoid_partial_spends is introduced It's a parameter used when building a tx and it's passed to coin_select. Later commits will introduce behavior for this flag
This commit introduces many changes but they don't _really_ change anything. Tests will still pass as usual. The main change is how UTXOs are treated on coin_selection. Before, each UTXO was treated individually, but now each UTXO is its own **group**. For now, group_utxos_if_applies just creates groups with a single UTXO inside of it, but future commits will add logic to this function so it groups by pub_key
Now avoid_partial_spends will work as intended. If passed as true, it will group utxos by pubkey, and if selected, the grouped UTXOs will be used together. Tests are added that check that new functionality works
15351ea to
5ac620b
Compare
| } | ||
| fn group_utxos_if_applies(utxos: Vec<WeightedUtxo>, _: bool) -> Vec<Vec<WeightedUtxo>> { | ||
| // No grouping: every UTXO is its own group. | ||
| return utxos.into_iter().map(|u| vec![u]).collect(); |
There was a problem hiding this comment.
why return utxos.into_iter().map(|u| vec![u]).collect(); and not utxos.into_iter().map(|u| vec![u]).collect() ?
|
Thanks for working on this, might take some time to get it reviewed but I'll bring it up on our next dev call (on our discord server, open to everyone if you'd like to join). |
|
FYI, I'm working on a feature based on this PR. Nodes with avoid_partial_spends off will still try to avoid partial spending if the new transaction's fee is not higher than the original. PR coming soon |
|
Looking at past PRs, |
closing and will work in the future |
In bitcoindevkit/bdk_wallet#28 this PR from Bitcoin Core was mentioned bitcoin/bitcoin#12257
This PR adds a param when building the tx called avoid_partial_spends. When true, it changes coin select to use output groups rather than outputs, where each output group corresponds to all outputs with the same destination.
It is a privacy improvement, as each time you spend some output, any other output that is publicly associated with the destination (address) will also be spent at the same time, at the cost of fee increase for cases where coin select without group restriction would find a more optimal set of coins (see example below).
For regular use without address reuse, this PR should have no effect on the user experience whatsoever; it only affects users who, for some reason, have multiple outputs with the same destination (i.e. address reuse).
Example: a node has four outputs linked to two addresses A and B:
The node sends 0.2 btc to C. Without -avoidpartialspends, the following coin selection will occur:
With -avoidpartialspends, the following will instead happen:
Assuming nobody sends to the address after you spend from it, you will only ever use one address once. The con is that the transaction becomes slightly larger in this case, because it is overpicking outputs to adhere to the no partial spending rule.
Checklists
All Submissions:
cargo fmtandcargo clippybefore committingNew Features:
Bugfixes: