wallet: skip available coins fetch if "other inputs" are disallowed

no need to waste resources calculating the wallet available coins if
they are not going to be used.

The 'm_allow_other_inputs=true` default value change is to correct
an ugly misleading behavior:

The tx creation process was having a workaround patch to automatically
fall back to select coins from the wallet if `m_allow_other_inputs=false`
(previous default value) and no manual inputs were selected.

This could be seen in master in flows like `sendtoaddress`, `sendmany`
and even the GUI, where the `m_allow_other_inputs` value isn't customized
and the wallet still selects and adds coins to the tx internally.
This commit is contained in:
furszy 2022-08-05 11:58:08 -03:00
parent fabc031048
commit 94c0766b0c
No known key found for this signature in database
GPG Key ID: 5DD23CCC686AA623
4 changed files with 27 additions and 11 deletions

View File

@ -289,7 +289,9 @@ bool SendCoinsDialog::PrepareSendText(QString& question_string, QString& informa
updateCoinControlState();
prepareStatus = model->prepareTransaction(*m_current_transaction, *m_coin_control);
CCoinControl coin_control = *m_coin_control;
coin_control.m_allow_other_inputs = !coin_control.HasSelected(); // future, could introduce a checkbox to customize this value.
prepareStatus = model->prepareTransaction(*m_current_transaction, coin_control);
// process prepareStatus and on error generate message shown to user
processSendCoinsReturn(prepareStatus,

View File

@ -37,7 +37,7 @@ public:
bool m_include_unsafe_inputs = false;
//! If true, the selection process can add extra unselected inputs from the wallet
//! while requires all selected inputs be used
bool m_allow_other_inputs = false;
bool m_allow_other_inputs = true;
//! Includes watch only addresses which are solvable
bool fAllowWatchOnly = false;
//! Override automatic min/max checks on fee, m_feerate must be set if true

View File

@ -579,7 +579,7 @@ std::optional<SelectionResult> SelectCoins(const CWallet& wallet, CoinsResult& a
}
// coin control -> return all selected outputs (we want all selected to go into the transaction for sure)
if (coin_control.HasSelected() && !coin_control.m_allow_other_inputs) {
if (!coin_control.m_allow_other_inputs) {
SelectionResult result(nTargetValue, SelectionAlgorithm::MANUAL);
result.AddInput(preset_inputs);
@ -893,14 +893,18 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal(
const CAmount not_input_fees = coin_selection_params.m_effective_feerate.GetFee(coin_selection_params.tx_noinputs_size);
CAmount selection_target = recipients_sum + not_input_fees;
// Get available coins
auto available_coins = AvailableCoins(wallet,
&coin_control,
coin_selection_params.m_effective_feerate,
1, /*nMinimumAmount*/
MAX_MONEY, /*nMaximumAmount*/
MAX_MONEY, /*nMinimumSumAmount*/
0); /*nMaximumCount*/
// Fetch wallet available coins if "other inputs" are
// allowed (coins automatically selected by the wallet)
CoinsResult available_coins;
if (coin_control.m_allow_other_inputs) {
available_coins = AvailableCoins(wallet,
&coin_control,
coin_selection_params.m_effective_feerate,
1, /*nMinimumAmount*/
MAX_MONEY, /*nMaximumAmount*/
MAX_MONEY, /*nMinimumSumAmount*/
0); /*nMaximumCount*/
}
// Choose coins to use
std::optional<SelectionResult> result = SelectCoins(wallet, available_coins, /*nTargetValue=*/selection_target, coin_control, coin_selection_params);

View File

@ -1095,6 +1095,8 @@ class RawTransactionsTest(BitcoinTestFramework):
# Expect: only preset inputs are used.
# 5. Explicit add_inputs=true, no preset inputs (same as (1) but with an explicit set):
# Expect: include inputs from the wallet.
# 6. Explicit add_inputs=false, no preset inputs:
# Expect: failure as we did not provide inputs and the process cannot automatically select coins.
# Case (1), 'send' command
# 'add_inputs' value is true unless "inputs" are specified, in such case, add_inputs=false.
@ -1146,6 +1148,10 @@ class RawTransactionsTest(BitcoinTestFramework):
tx = wallet.send(outputs=[{addr1: 8}], options=options)
assert tx["complete"]
# 6. Explicit add_inputs=false, no preset inputs:
options = {"add_inputs": False}
assert_raises_rpc_error(-4, "Insufficient funds", wallet.send, outputs=[{addr1: 3}], options=options)
################################################
# Case (1), 'walletcreatefundedpsbt' command
@ -1187,6 +1193,10 @@ class RawTransactionsTest(BitcoinTestFramework):
}
assert "psbt" in wallet.walletcreatefundedpsbt(inputs=[], outputs=outputs, options=options)
# Case (6). Explicit add_inputs=false, no preset inputs:
options = {"add_inputs": False}
assert_raises_rpc_error(-4, "Insufficient funds", wallet.walletcreatefundedpsbt, inputs=[], outputs=outputs, options=options)
self.nodes[2].unloadwallet("test_preset_inputs")
def test_weight_calculation(self):