[feature] Wallet-level minimum input value for automatic coin selection
Problem
Dogecoin Core has two independent dust mechanisms today, and both of them govern outputs, not inputs:
- Relay / mempool policy --
-dustlimitand-harddustlimit(src/policy/policy.cpp:212-213, defaults insrc/policy/policy.h:70,81). These control what the node accepts and relays. - Wallet output policy --
-discardthreshold(src/wallet/wallet.cpp:65-69, defaultDEFAULT_DISCARD_THRESHOLD = COIN / 100). The comment in the source is explicit: outputs smaller than this get rejected, change smaller than this gets discarded to fee.
There is no equivalent policy on the input side. CWallet::CreateTransaction
gathers spendable coins with:
// src/wallet/wallet.cpp:2484
AvailableCoins(vAvailableCoins, true, coinControl);CWallet::AvailableCoins (src/wallet/wallet.cpp:1996) already accepts an
nMinimumAmount parameter and filters on it at line 2063:
if (pcoin->tx->vout[i].nValue < nMinimumAmount || pcoin->tx->vout[i].nValue > nMaximumAmount)
continue;but the CreateTransaction call site passes no value, so the default of 1 koinu
applies and every dust UTXO in the wallet is eligible for automatic selection.
The practical consequence: a wallet configured to never create outputs below 0.01 DOGE will still silently consume arbitrarily small received outputs, merging them with the user's other coins. For users targeted by dust-based address-linking (see #3544 for the network-side discussion of large-scale dust on Dogecoin), the only current defence is manual Coin Control, which is impractical for non-technical users and offers no protection against accidental consolidation.
Proposed solution
An opt-in wallet-level minimum input value, applied only to automatic coin selection.
Expected behaviour
- New startup option, e.g.
-mininputvalue=<amt>, default0(disabled, exactly today's behaviour). - When set, UTXOs below the threshold are excluded from automatic selection.
- The filter must be applied at the
CreateTransactioncall site (wallet.cpp:2484), not insideAvailableCoinsand not by changing its default parameter.WalletModel::listCoins(src/qt/walletmodel.cpp:585) and the Coin Control dialog use the same function; filtering insideAvailableCoinswould hide the coins from the Coin Control UI and make them unspendable through the documented escape hatch. - Manual selection via Coin Control and
CCoinControl::Selectremains unaffected: preset inputs are added inCWallet::SelectCoinsbefore the automatic passes. - No consensus, mempool, or relay behaviour changes.
- No balance change:
CWallet::GetBalance(wallet.cpp:1906) iteratesmapWalletand does not go throughAvailableCoins, so filtered coins remain fully counted.
Why not reuse an existing parameter
-dustlimit/-harddustlimitare network policy. A node operator may legitimately want to relay dust while not spending it, and vice versa.-discardthresholdis wallet output policy and is validated to be at least the dust limit (wallet.cpp:3977-3980) specifically to avoid creating stuck transactions. Overloading it with input-selection semantics would couple two unrelated decisions, and raising it to protect inputs would also change change- discard behaviour and fee outcomes.
Scope of the change
Small, because the filtering primitive already exists:
src/wallet/wallet.cpp-- parse and validate the new option next to the existing-discardthresholdhandling (~3971), pass it asnMinimumAmountat theCreateTransactioncall site (2484).src/wallet/wallet.h-- static member and default constant alongsideDEFAULT_DISCARD_THRESHOLD.- Optionally
CCoinControl-- a per-call override, so RPCs such assendtoaddressandfundrawtransactioncan opt out.
No RPC surface change is required for inspection: listunspent already exposes
query_options.minimumAmount (src/wallet/rpcwallet.cpp:2680), which is
sufficient for users to enumerate the outputs the filter would skip.
Testing
Functional tests to add:
- default (
0) reproduces current selection results byte for byte; - with a threshold set, sub-threshold UTXOs are not selected automatically;
- the same UTXOs are still spendable when passed explicitly via Coin Control;
getbalanceis unchanged with the filter active;- a wallet whose entire balance is below the threshold fails with a clear insufficient-funds error rather than an opaque one.
Alternatives considered
- Manual Coin Control only (status quo): requires per-transaction attention and does not prevent accidental consolidation.
- Raising
-discardthreshold: wrong axis; it governs outputs, and raising it increases change discarded to fee. - Filtering inside
AvailableCoins: breaks Coin Control andlistCoins, as described above.
Notes
Filed as a design proposal, not a bug. Happy to open a PR against the current development branch if maintainers agree with the direction and the option name.
Source: dogecoin/dogecoin