Skip to content

Commit 44d8172

Browse files
committed
Merge #13756: wallet: "avoid_reuse" wallet flag for improved privacy
5ebc6b0 bitcoind: update -avoidpartialspends description to account for auto-enable for avoid_reuse wallets (Karl-Johan Alm) ada258f doc: release notes for avoid_reuse (Karl-Johan Alm) 2766955 wallet: enable avoid_partial_spends by default if avoid_reuse is set (Karl-Johan Alm) 8f2e208 test: add test for avoidreuse feature (Karl-Johan Alm) 0bdfbd3 wallet/rpc: add 'avoid_reuse' option to RPC commands (Karl-Johan Alm) f904723 wallet/rpc: add setwalletflag RPC and MUTABLE_WALLET_FLAGS (Karl-Johan Alm) 8247a0d wallet: enable avoid_reuse feature (Karl-Johan Alm) eec1566 wallet: avoid reuse flags (Karl-Johan Alm) 5892809 wallet: make IsWalletFlagSet() const (Karl-Johan Alm) 129a5ba wallet: rename g_known_wallet_flags constant to KNOWN_WALLET_FLAGS (Karl-Johan Alm) Pull request description: Add a new wallet flag called `avoid_reuse` which, when enabled, will keep track of when a specific destination has been spent from, and will actively "blacklist" any new UTXOs which send to an already-spent-from destination. This improves privacy, as a payer could otherwise begin tracking a payee's wallet by regularly peppering a known UTXO with dust outputs, which would then be scooped up and used in payments by the payee, allowing the payer to map out (1) the inputs owned by the payee and (2) the destinations to which the payee is making payments. This replaces #10386 and together with the (now merged) #12257 it addresses #10065 in full. The concerns raised in bitcoin/bitcoin#10386 (comment) are also addressed due to #12257. ~~Note: this builds on top of #15780.~~ (merged) ACKs for commit 5ebc6b: jnewbery: ACK 5ebc6b0 laanwj: Concept and code-review ACK 5ebc6b0 meshcollider: Code review ACK bitcoin/bitcoin@5ebc6b0 achow101: ACK 5ebc6b0 modulo above nits Tree-SHA512: fdef45826af544cbbb45634ac367852cc467ec87081d86d08b53ca849e588617e9a0a255b7e7bb28692d15332de58d6c3d274ac003355220e4213d7d9070742e
2 parents ac4d38c + 5ebc6b0 commit 44d8172

File tree

11 files changed

+476
-27
lines changed

11 files changed

+476
-27
lines changed

doc/release-notes-13756.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
Coin selection
2+
--------------
3+
4+
### Reuse Avoidance
5+
6+
A new wallet flag `avoid_reuse` has been added (default off). When enabled,
7+
a wallet will distinguish between used and unused addresses, and default to not
8+
use the former in coin selection.
9+
10+
(Note: rescanning the blockchain is required, to correctly mark previously
11+
used destinations.)
12+
13+
Together with "avoid partial spends" (present as of Bitcoin v0.17), this
14+
addresses a serious privacy issue where a malicious user can track spends by
15+
peppering a previously paid to address with near-dust outputs, which would then
16+
be inadvertently included in future payments.
17+
18+
New RPCs
19+
--------
20+
21+
- A new `setwalletflag` RPC sets/unsets flags for an existing wallet.
22+
23+
24+
Updated RPCs
25+
------------
26+
27+
Several RPCs have been updated to include an "avoid_reuse" flag, used to control
28+
whether already used addresses should be left out or included in the operation.
29+
These include:
30+
31+
- createwallet
32+
- getbalance
33+
- sendtoaddress
34+
35+
In addition, `sendtoaddress` has been changed to enable `-avoidpartialspends` when
36+
`avoid_reuse` is enabled.
37+
38+
The listunspent RPC has also been updated to now include a "reused" bool, for nodes
39+
with "avoid_reuse" enabled.

src/rpc/client.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
3636
{ "sendtoaddress", 4, "subtractfeefromamount" },
3737
{ "sendtoaddress", 5 , "replaceable" },
3838
{ "sendtoaddress", 6 , "conf_target" },
39+
{ "sendtoaddress", 8, "avoid_reuse" },
3940
{ "settxfee", 0, "amount" },
4041
{ "sethdseed", 0, "newkeypool" },
4142
{ "getreceivedbyaddress", 1, "minconf" },
@@ -48,6 +49,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
4849
{ "listreceivedbylabel", 2, "include_watchonly" },
4950
{ "getbalance", 1, "minconf" },
5051
{ "getbalance", 2, "include_watchonly" },
52+
{ "getbalance", 3, "avoid_reuse" },
5153
{ "getblockhash", 0, "height" },
5254
{ "waitforblockheight", 0, "height" },
5355
{ "waitforblockheight", 1, "timeout" },
@@ -141,6 +143,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
141143
{ "setban", 2, "bantime" },
142144
{ "setban", 3, "absolute" },
143145
{ "setnetworkactive", 0, "state" },
146+
{ "setwalletflag", 1, "value" },
144147
{ "getmempoolancestors", 1, "verbose" },
145148
{ "getmempooldescendants", 1, "verbose" },
146149
{ "bumpfee", 1, "options" },
@@ -162,6 +165,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
162165
{ "rescanblockchain", 1, "stop_height"},
163166
{ "createwallet", 1, "disable_private_keys"},
164167
{ "createwallet", 2, "blank"},
168+
{ "createwallet", 4, "avoid_reuse"},
165169
{ "getnodeaddresses", 0, "count"},
166170
{ "stop", 0, "wait" },
167171
};

src/script/ismine.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ enum isminetype
2020
ISMINE_NO = 0,
2121
ISMINE_WATCH_ONLY = 1 << 0,
2222
ISMINE_SPENDABLE = 1 << 1,
23+
ISMINE_USED = 1 << 2,
2324
ISMINE_ALL = ISMINE_WATCH_ONLY | ISMINE_SPENDABLE,
25+
ISMINE_ALL_USED = ISMINE_ALL | ISMINE_USED,
2426
ISMINE_ENUM_ELEMENTS,
2527
};
2628
/** used for bitflags of isminetype */

src/wallet/coincontrol.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ void CCoinControl::SetNull()
1313
fAllowOtherInputs = false;
1414
fAllowWatchOnly = false;
1515
m_avoid_partial_spends = gArgs.GetBoolArg("-avoidpartialspends", DEFAULT_AVOIDPARTIALSPENDS);
16+
m_avoid_address_reuse = false;
1617
setSelected.clear();
1718
m_feerate.reset();
1819
fOverrideFeeRate = false;

src/wallet/coincontrol.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ class CCoinControl
3434
boost::optional<bool> m_signal_bip125_rbf;
3535
//! Avoid partial use of funds sent to a given address
3636
bool m_avoid_partial_spends;
37+
//! Forbids inclusion of dirty (previously used) addresses
38+
bool m_avoid_address_reuse;
3739
//! Fee estimation mode to control arguments to estimateSmartFee
3840
FeeEstimateMode m_fee_mode;
3941
//! Minimum chain depth value for coin availability

src/wallet/init.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ const WalletInitInterface& g_wallet_init_interface = WalletInit();
3434
void WalletInit::AddWalletOptions() const
3535
{
3636
gArgs.AddArg("-addresstype", strprintf("What type of addresses to use (\"legacy\", \"p2sh-segwit\", or \"bech32\", default: \"%s\")", FormatOutputType(DEFAULT_ADDRESS_TYPE)), false, OptionsCategory::WALLET);
37-
gArgs.AddArg("-avoidpartialspends", strprintf("Group outputs by address, selecting all or none, instead of selecting on a per-output basis. Privacy is improved as an address is only used once (unless someone sends to it after spending from it), but may result in slightly higher fees as suboptimal coin selection may result due to the added limitation (default: %u)", DEFAULT_AVOIDPARTIALSPENDS), false, OptionsCategory::WALLET);
37+
gArgs.AddArg("-avoidpartialspends", strprintf("Group outputs by address, selecting all or none, instead of selecting on a per-output basis. Privacy is improved as an address is only used once (unless someone sends to it after spending from it), but may result in slightly higher fees as suboptimal coin selection may result due to the added limitation (default: %u (always enabled for wallets with \"avoid_reuse\" enabled))", DEFAULT_AVOIDPARTIALSPENDS), false, OptionsCategory::WALLET);
3838
gArgs.AddArg("-changetype", "What type of change to use (\"legacy\", \"p2sh-segwit\", or \"bech32\"). Default is same as -addresstype, except when -addresstype=p2sh-segwit a native segwit output is used when sending to a native segwit address)", false, OptionsCategory::WALLET);
3939
gArgs.AddArg("-disablewallet", "Do not load the wallet and disable wallet RPC calls", false, OptionsCategory::WALLET);
4040
gArgs.AddArg("-discardfee=<amt>", strprintf("The fee rate (in %s/kB) that indicates your tolerance for discarding change by adding it to the fee (default: %s). "

0 commit comments

Comments
 (0)