diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index a054cb3fea..06b2808494 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2370,12 +2370,12 @@ bool CWallet::SelectCoins(const std::vector& vAvailableCoins, const CAm std::vector vCoins(vAvailableCoins); CAmountMap value_to_select = mapTargetValue; + // Default to bnb was not used. If we use it, we set it later + bnb_used = false; + // coin control -> return all selected outputs (we want all selected to go into the transaction for sure) if (coin_control.HasSelected() && !coin_control.fAllowOtherInputs) { - // We didn't use BnB here, so set it to false. - bnb_used = false; - for (const COutput& out : vCoins) { if (!out.fSpendable) @@ -2405,7 +2405,6 @@ bool CWallet::SelectCoins(const std::vector& vAvailableCoins, const CAm const CWalletTx& wtx = it->second; // Clearly invalid input, fail if (wtx.tx->vout.size() <= outpoint.n) { - bnb_used = false; return false; } // Just to calculate the marginal byte size @@ -2416,7 +2415,6 @@ bool CWallet::SelectCoins(const std::vector& vAvailableCoins, const CAm CInputCoin coin(&wtx, outpoint.n, wtx.GetSpendSize(outpoint.n, false)); mapValueFromPresetInputs[wtx.GetOutputAsset(outpoint.n)] += amt; if (coin.m_input_bytes <= 0) { - bnb_used = false; return false; // Not solvable, can't estimate size for fee } coin.effective_value = coin.value - coin_selection_params.effective_fee.GetFee(coin.m_input_bytes); @@ -2427,7 +2425,6 @@ bool CWallet::SelectCoins(const std::vector& vAvailableCoins, const CAm } setPresetCoins.insert(coin); } else { - bnb_used = false; return false; // TODO: Allow non-wallet inputs } } @@ -3030,7 +3027,7 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std } // Choose coins to use - bool bnb_used; + bool bnb_used = false; if (pick_new_inputs) { mapValueIn.clear(); setCoins.clear(); diff --git a/test/functional/rpc_fundrawtransaction.py b/test/functional/rpc_fundrawtransaction.py index 82b59e1b7f..46b6183dec 100755 --- a/test/functional/rpc_fundrawtransaction.py +++ b/test/functional/rpc_fundrawtransaction.py @@ -93,6 +93,7 @@ class RawTransactionsTest(BitcoinTestFramework): self.test_option_feerate() self.test_address_reuse() self.test_option_subtract_fee_from_outputs() + self.test_subtract_fee_with_presets() def test_change_position(self): """Ensure setting changePosition in fundraw with an exact match is handled properly.""" @@ -767,5 +768,18 @@ class RawTransactionsTest(BitcoinTestFramework): # The total subtracted from the outputs is equal to the fee. assert_equal(share[0] + share[2] + share[3], result[0]['fee']) + def test_subtract_fee_with_presets(self): + self.log.info("Test fundrawtxn subtract fee from outputs with preset inputs that are sufficient") + + addr = self.nodes[0].getnewaddress() + txid = self.nodes[0].sendtoaddress(addr, 10) + vout = find_vout_for_address(self.nodes[0], txid, addr) + + rawtx = self.nodes[0].createrawtransaction([{'txid': txid, 'vout': vout}], [{self.nodes[0].getnewaddress(): 5}]) + fundedtx = self.nodes[0].fundrawtransaction(rawtx, {'subtractFeeFromOutputs': [0]}) + blindedtx = self.nodes[0].blindrawtransaction(fundedtx['hex']) + signedtx = self.nodes[0].signrawtransactionwithwallet(blindedtx) + self.nodes[0].sendrawtransaction(signedtx['hex']) + if __name__ == '__main__': RawTransactionsTest().main()