Skip to content

Commit bc28ca3

Browse files
committed
Merge bitcoin/bitcoin#25118: wallet: unify “allow/block other inputs“ concept
d338712 scripted-diff: rename fAllowOtherInputs -> m_allow_other_inputs (furszy) 8dea74a refactor: use GetWalletTx in SelectCoins instead of access mapWallet (furszy) b4e2d4d wallet: move "use-only coinControl inputs" below the selected inputs lookup (furszy) 25749f1 wallet: unify “allow/block other inputs“ concept (furszy) Pull request description: Seeking to make the `CoinControl` options less confusing/redundant. It should have no functional changes. The too long to read technical description; remove `m_add_inputs`, we can use the already existent `fAllowOtherInputs` flag. In #16377 the `CoinControl` flag ‘m_add_inputs’ was added to tell the coin filtering and selection process two things: - Coin Filtering: Only use the provided inputs. Skip the Rest. - Coin Selection: Search the wtxs-outputs and append all the `CoinControl` internal and external selected outpoints to the selection result (skipping all the available output checks). Nothing else. Meanwhile, in `CoinControl` we already have a flag ‘fAllowOtherInputs’ which is already saying: - Coin Filtering: Only use the provided inputs. Skip the Rest. - Coin Selection: If false, no selection process -> append all the `CoinControl` selected outpoints to the selection result (while they passed all the `AvailableCoins` checks and are available in the 'vCoins' vector). ### Changes As can notice, the first point in the coin filtering process is duplicated in the two option flags. And the second one, is slightly different merely because it takes into account whether the coin is on the `AvailableCoins` vector or not. So it makes sense to merge ‘m_add_inputs’ and ‘fAllowOtherInputs’ into a single field for the coin filtering process while introduce other changes to add the missing/skipped internal and external coins into 'vCoins' vector if they were manually selected by the user. —————————————————————————————————— Just as an extra note: On top of this, I’m working on unifying/untangling further the coin filtering and selection processes so we have less duplicate functionality in both processes. ACKs for top commit: laanwj: Code review ACK d338712 Tree-SHA512: 98920b80dd787cfe737dacd4c59575dfa8393c799b55f2aaef9aed2b15c61470715a88663557b49c7400938220f99af7690be01980a8684f4f71947407f21750
2 parents 57a491b + d338712 commit bc28ca3

File tree

5 files changed

+26
-43
lines changed

5 files changed

+26
-43
lines changed

src/wallet/coincontrol.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,11 @@ class CCoinControl
3333
CTxDestination destChange = CNoDestination();
3434
//! Override the default change type if set, ignored if destChange is set
3535
std::optional<OutputType> m_change_type;
36-
//! If false, only selected inputs are used
37-
bool m_add_inputs = true;
3836
//! If false, only safe inputs will be used
3937
bool m_include_unsafe_inputs = false;
40-
//! If false, allows unselected inputs, but requires all selected inputs be used
41-
bool fAllowOtherInputs = false;
38+
//! If true, the selection process can add extra unselected inputs from the wallet
39+
//! while requires all selected inputs be used
40+
bool m_allow_other_inputs = false;
4241
//! Includes watch only addresses which are solvable
4342
bool fAllowWatchOnly = false;
4443
//! Override automatic min/max checks on fee, m_feerate must be set if true

src/wallet/feebumper.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ Result CreateRateBumpTransaction(CWallet& wallet, const uint256& txid, const CCo
213213
for (const auto& inputs : wtx.tx->vin) {
214214
new_coin_control.Select(COutPoint(inputs.prevout));
215215
}
216-
new_coin_control.fAllowOtherInputs = true;
216+
new_coin_control.m_allow_other_inputs = true;
217217

218218
// We cannot source new unconfirmed inputs(bip125 rule 2)
219219
new_coin_control.m_min_depth = 1;

src/wallet/rpc/spend.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -535,8 +535,8 @@ void FundTransaction(CWallet& wallet, CMutableTransaction& tx, CAmount& fee_out,
535535
},
536536
true, true);
537537

538-
if (options.exists("add_inputs") ) {
539-
coinControl.m_add_inputs = options["add_inputs"].get_bool();
538+
if (options.exists("add_inputs")) {
539+
coinControl.m_allow_other_inputs = options["add_inputs"].get_bool();
540540
}
541541

542542
if (options.exists("changeAddress") || options.exists("change_address")) {
@@ -823,7 +823,7 @@ RPCHelpMan fundrawtransaction()
823823
int change_position;
824824
CCoinControl coin_control;
825825
// Automatically select (additional) coins. Can be overridden by options.add_inputs.
826-
coin_control.m_add_inputs = true;
826+
coin_control.m_allow_other_inputs = true;
827827
FundTransaction(*pwallet, tx, fee, change_position, request.params[1], coin_control, /*override_min_fee=*/true);
828828

829829
UniValue result(UniValue::VOBJ);
@@ -1225,7 +1225,7 @@ RPCHelpMan send()
12251225
CCoinControl coin_control;
12261226
// Automatically select coins, unless at least one is manually selected. Can
12271227
// be overridden by options.add_inputs.
1228-
coin_control.m_add_inputs = rawTx.vin.size() == 0;
1228+
coin_control.m_allow_other_inputs = rawTx.vin.size() == 0;
12291229
SetOptionsInputWeights(options["inputs"], options);
12301230
FundTransaction(*pwallet, rawTx, fee, change_position, options, coin_control, /*override_min_fee=*/false);
12311231

@@ -1649,7 +1649,7 @@ RPCHelpMan walletcreatefundedpsbt()
16491649
CCoinControl coin_control;
16501650
// Automatically select coins, unless at least one is manually selected. Can
16511651
// be overridden by options.add_inputs.
1652-
coin_control.m_add_inputs = rawTx.vin.size() == 0;
1652+
coin_control.m_allow_other_inputs = rawTx.vin.size() == 0;
16531653
SetOptionsInputWeights(request.params[0], options);
16541654
FundTransaction(wallet, rawTx, fee, change_position, options, coin_control, /*override_min_fee=*/true);
16551655

src/wallet/spend.cpp

Lines changed: 15 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -168,15 +168,10 @@ CoinsResult AvailableCoins(const CWallet& wallet,
168168
const CTxOut& output = wtx.tx->vout[i];
169169
const COutPoint outpoint(wtxid, i);
170170

171-
// Only consider selected coins if add_inputs is false
172-
if (coinControl && !coinControl->m_add_inputs && !coinControl->IsSelected(outpoint)) {
173-
continue;
174-
}
175-
176171
if (output.nValue < nMinimumAmount || output.nValue > nMaximumAmount)
177172
continue;
178173

179-
if (coinControl && coinControl->HasSelected() && !coinControl->fAllowOtherInputs && !coinControl->IsSelected(outpoint))
174+
if (coinControl && coinControl->HasSelected() && !coinControl->m_allow_other_inputs && !coinControl->IsSelected(outpoint))
180175
continue;
181176

182177
if (wallet.IsLockedCoin(outpoint))
@@ -438,23 +433,6 @@ std::optional<SelectionResult> SelectCoins(const CWallet& wallet, const std::vec
438433

439434
OutputGroup preset_inputs(coin_selection_params);
440435

441-
// coin control -> return all selected outputs (we want all selected to go into the transaction for sure)
442-
if (coin_control.HasSelected() && !coin_control.fAllowOtherInputs)
443-
{
444-
for (const COutput& out : vCoins) {
445-
if (!out.spendable) continue;
446-
/* Set ancestors and descendants to 0 as these don't matter for preset inputs as no actual selection is being done.
447-
* positive_only is set to false because we want to include all preset inputs, even if they are dust.
448-
*/
449-
preset_inputs.Insert(out, /*ancestors=*/ 0, /*descendants=*/ 0, /*positive_only=*/ false);
450-
}
451-
SelectionResult result(nTargetValue, SelectionAlgorithm::MANUAL);
452-
result.AddInput(preset_inputs);
453-
if (result.GetSelectedValue() < nTargetValue) return std::nullopt;
454-
result.ComputeAndSetWaste(coin_selection_params.m_cost_of_change);
455-
return result;
456-
}
457-
458436
// calculate value from preset inputs and store them
459437
std::set<COutPoint> preset_coins;
460438

@@ -463,15 +441,14 @@ std::optional<SelectionResult> SelectCoins(const CWallet& wallet, const std::vec
463441
for (const COutPoint& outpoint : vPresetInputs) {
464442
int input_bytes = -1;
465443
CTxOut txout;
466-
std::map<uint256, CWalletTx>::const_iterator it = wallet.mapWallet.find(outpoint.hash);
467-
if (it != wallet.mapWallet.end()) {
468-
const CWalletTx& wtx = it->second;
444+
auto ptr_wtx = wallet.GetWalletTx(outpoint.hash);
445+
if (ptr_wtx) {
469446
// Clearly invalid input, fail
470-
if (wtx.tx->vout.size() <= outpoint.n) {
447+
if (ptr_wtx->tx->vout.size() <= outpoint.n) {
471448
return std::nullopt;
472449
}
473-
input_bytes = GetTxSpendSize(wallet, wtx, outpoint.n, false);
474-
txout = wtx.tx->vout.at(outpoint.n);
450+
input_bytes = GetTxSpendSize(wallet, *ptr_wtx, outpoint.n, false);
451+
txout = ptr_wtx->tx->vout.at(outpoint.n);
475452
} else {
476453
// The input is external. We did not find the tx in mapWallet.
477454
if (!coin_control.GetExternalOutput(outpoint, txout)) {
@@ -502,6 +479,15 @@ std::optional<SelectionResult> SelectCoins(const CWallet& wallet, const std::vec
502479
preset_inputs.Insert(output, /*ancestors=*/ 0, /*descendants=*/ 0, /*positive_only=*/ false);
503480
}
504481

482+
// coin control -> return all selected outputs (we want all selected to go into the transaction for sure)
483+
if (coin_control.HasSelected() && !coin_control.m_allow_other_inputs) {
484+
SelectionResult result(nTargetValue, SelectionAlgorithm::MANUAL);
485+
result.AddInput(preset_inputs);
486+
if (result.GetSelectedValue() < nTargetValue) return std::nullopt;
487+
result.ComputeAndSetWaste(coin_selection_params.m_cost_of_change);
488+
return result;
489+
}
490+
505491
// remove preset inputs from vCoins so that Coin Selection doesn't pick them.
506492
for (std::vector<COutput>::iterator it = vCoins.begin(); it != vCoins.end() && coin_control.HasSelected();)
507493
{
@@ -1033,8 +1019,6 @@ bool FundTransaction(CWallet& wallet, CMutableTransaction& tx, CAmount& nFeeRet,
10331019
vecSend.push_back(recipient);
10341020
}
10351021

1036-
coinControl.fAllowOtherInputs = true;
1037-
10381022
// Acquire the locks to prevent races to the new locked unspents between the
10391023
// CreateTransaction call and LockCoin calls (when lockUnspents is true).
10401024
LOCK(wallet.cs_wallet);

src/wallet/test/coinselector_tests.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
336336
add_coin(coins, *wallet, 3 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
337337
add_coin(coins, *wallet, 2 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
338338
CCoinControl coin_control;
339-
coin_control.fAllowOtherInputs = true;
339+
coin_control.m_allow_other_inputs = true;
340340
coin_control.Select(coins.at(0).outpoint);
341341
coin_selection_params_bnb.m_effective_feerate = CFeeRate(0);
342342
const auto result10 = SelectCoins(*wallet, coins, 10 * CENT, coin_control, coin_selection_params_bnb);
@@ -392,7 +392,7 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
392392
expected_result.Clear();
393393
add_coin(9 * CENT, 2, expected_result);
394394
add_coin(1 * CENT, 2, expected_result);
395-
coin_control.fAllowOtherInputs = true;
395+
coin_control.m_allow_other_inputs = true;
396396
coin_control.Select(coins.at(1).outpoint); // pre select 9 coin
397397
const auto result13 = SelectCoins(*wallet, coins, 10 * CENT, coin_control, coin_selection_params_bnb);
398398
BOOST_CHECK(EquivalentResult(expected_result, *result13));

0 commit comments

Comments
 (0)