@@ -2234,7 +2234,11 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const CoinEligibil
2234
2234
if (effective_value > 0 ) {
2235
2235
group.fee += coin.m_input_bytes < 0 ? 0 : coin_selection_params.effective_fee .GetFee (coin.m_input_bytes );
2236
2236
group.long_term_fee += coin.m_input_bytes < 0 ? 0 : long_term_feerate.GetFee (coin.m_input_bytes );
2237
- group.effective_value += effective_value;
2237
+ if (coin_selection_params.m_subtract_fee_outputs ) {
2238
+ group.effective_value += coin.txout .nValue ;
2239
+ } else {
2240
+ group.effective_value += effective_value;
2241
+ }
2238
2242
++it;
2239
2243
} else {
2240
2244
it = group.Discard (coin);
@@ -2260,6 +2264,7 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const CoinEligibil
2260
2264
bool CWallet::SelectCoins (const std::vector<COutput>& vAvailableCoins, const CAmount& nTargetValue, std::set<CInputCoin>& setCoinsRet, CAmount& nValueRet, const CCoinControl& coin_control, CoinSelectionParams& coin_selection_params, bool & bnb_used) const
2261
2265
{
2262
2266
std::vector<COutput> vCoins (vAvailableCoins);
2267
+ CAmount value_to_select = nTargetValue;
2263
2268
2264
2269
// coin control -> return all selected outputs (we want all selected to go into the transaction for sure)
2265
2270
if (coin_control.HasSelected () && !coin_control.fAllowOtherInputs )
@@ -2285,22 +2290,33 @@ bool CWallet::SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAm
2285
2290
coin_control.ListSelected (vPresetInputs);
2286
2291
for (const COutPoint& outpoint : vPresetInputs)
2287
2292
{
2288
- // For now, don't use BnB if preset inputs are selected. TODO: Enable this later
2289
- bnb_used = false ;
2290
- coin_selection_params.use_bnb = false ;
2291
-
2292
2293
std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find (outpoint.hash );
2293
2294
if (it != mapWallet.end ())
2294
2295
{
2295
2296
const CWalletTx& wtx = it->second ;
2296
2297
// Clearly invalid input, fail
2297
- if (wtx.tx ->vout .size () <= outpoint.n )
2298
+ if (wtx.tx ->vout .size () <= outpoint.n ) {
2299
+ bnb_used = false ;
2298
2300
return false ;
2301
+ }
2299
2302
// Just to calculate the marginal byte size
2300
- nValueFromPresetInputs += wtx.tx ->vout [outpoint.n ].nValue ;
2301
- setPresetCoins.insert (CInputCoin (wtx.tx , outpoint.n ));
2302
- } else
2303
+ CInputCoin coin (wtx.tx , outpoint.n , wtx.GetSpendSize (outpoint.n , false ));
2304
+ nValueFromPresetInputs += coin.txout .nValue ;
2305
+ if (coin.m_input_bytes <= 0 ) {
2306
+ bnb_used = false ;
2307
+ return false ; // Not solvable, can't estimate size for fee
2308
+ }
2309
+ coin.effective_value = coin.txout .nValue - coin_selection_params.effective_fee .GetFee (coin.m_input_bytes );
2310
+ if (coin_selection_params.use_bnb ) {
2311
+ value_to_select -= coin.effective_value ;
2312
+ } else {
2313
+ value_to_select -= coin.txout .nValue ;
2314
+ }
2315
+ setPresetCoins.insert (coin);
2316
+ } else {
2317
+ bnb_used = false ;
2303
2318
return false ; // TODO: Allow non-wallet inputs
2319
+ }
2304
2320
}
2305
2321
2306
2322
// remove preset inputs from vCoins
@@ -2329,14 +2345,14 @@ bool CWallet::SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAm
2329
2345
size_t max_descendants = (size_t )std::max<int64_t >(1 , limit_descendant_count);
2330
2346
bool fRejectLongChains = gArgs .GetBoolArg (" -walletrejectlongchains" , DEFAULT_WALLET_REJECT_LONG_CHAINS);
2331
2347
2332
- bool res = nTargetValue <= nValueFromPresetInputs ||
2333
- SelectCoinsMinConf (nTargetValue - nValueFromPresetInputs , CoinEligibilityFilter (1 , 6 , 0 ), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used) ||
2334
- SelectCoinsMinConf (nTargetValue - nValueFromPresetInputs , CoinEligibilityFilter (1 , 1 , 0 ), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used) ||
2335
- (m_spend_zero_conf_change && SelectCoinsMinConf (nTargetValue - nValueFromPresetInputs , CoinEligibilityFilter (0 , 1 , 2 ), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) ||
2336
- (m_spend_zero_conf_change && SelectCoinsMinConf (nTargetValue - nValueFromPresetInputs , CoinEligibilityFilter (0 , 1 , std::min ((size_t )4 , max_ancestors/3 ), std::min ((size_t )4 , max_descendants/3 )), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) ||
2337
- (m_spend_zero_conf_change && SelectCoinsMinConf (nTargetValue - nValueFromPresetInputs , CoinEligibilityFilter (0 , 1 , max_ancestors/2 , max_descendants/2 ), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) ||
2338
- (m_spend_zero_conf_change && SelectCoinsMinConf (nTargetValue - nValueFromPresetInputs , CoinEligibilityFilter (0 , 1 , max_ancestors-1 , max_descendants-1 ), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) ||
2339
- (m_spend_zero_conf_change && !fRejectLongChains && SelectCoinsMinConf (nTargetValue - nValueFromPresetInputs , CoinEligibilityFilter (0 , 1 , std::numeric_limits<uint64_t >::max ()), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used));
2348
+ bool res = value_to_select <= 0 ||
2349
+ SelectCoinsMinConf (value_to_select , CoinEligibilityFilter (1 , 6 , 0 ), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used) ||
2350
+ SelectCoinsMinConf (value_to_select , CoinEligibilityFilter (1 , 1 , 0 ), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used) ||
2351
+ (m_spend_zero_conf_change && SelectCoinsMinConf (value_to_select , CoinEligibilityFilter (0 , 1 , 2 ), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) ||
2352
+ (m_spend_zero_conf_change && SelectCoinsMinConf (value_to_select , CoinEligibilityFilter (0 , 1 , std::min ((size_t )4 , max_ancestors/3 ), std::min ((size_t )4 , max_descendants/3 )), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) ||
2353
+ (m_spend_zero_conf_change && SelectCoinsMinConf (value_to_select , CoinEligibilityFilter (0 , 1 , max_ancestors/2 , max_descendants/2 ), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) ||
2354
+ (m_spend_zero_conf_change && SelectCoinsMinConf (value_to_select , CoinEligibilityFilter (0 , 1 , max_ancestors-1 , max_descendants-1 ), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) ||
2355
+ (m_spend_zero_conf_change && !fRejectLongChains && SelectCoinsMinConf (value_to_select , CoinEligibilityFilter (0 , 1 , std::numeric_limits<uint64_t >::max ()), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used));
2340
2356
2341
2357
// because SelectCoinsMinConf clears the setCoinsRet, we now add the possible inputs to the coinset
2342
2358
util::insert (setCoinsRet, setPresetCoins);
@@ -2602,7 +2618,8 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std
2602
2618
2603
2619
// BnB selector is the only selector used when this is true.
2604
2620
// That should only happen on the first pass through the loop.
2605
- coin_selection_params.use_bnb = nSubtractFeeFromAmount == 0 ; // If we are doing subtract fee from recipient, then don't use BnB
2621
+ coin_selection_params.use_bnb = true ;
2622
+ coin_selection_params.m_subtract_fee_outputs = nSubtractFeeFromAmount != 0 ; // If we are doing subtract fee from recipient, don't use effective values
2606
2623
// Start with no fee and loop until there is enough fee
2607
2624
while (true )
2608
2625
{
@@ -2616,7 +2633,9 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std
2616
2633
nValueToSelect += nFeeRet;
2617
2634
2618
2635
// vouts to the payees
2619
- coin_selection_params.tx_noinputs_size = 11 ; // Static vsize overhead + outputs vsize. 4 nVersion, 4 nLocktime, 1 input count, 1 output count, 1 witness overhead (dummy, flag, stack size)
2636
+ if (!coin_selection_params.m_subtract_fee_outputs ) {
2637
+ coin_selection_params.tx_noinputs_size = 11 ; // Static vsize overhead + outputs vsize. 4 nVersion, 4 nLocktime, 1 input count, 1 output count, 1 witness overhead (dummy, flag, stack size)
2638
+ }
2620
2639
for (const auto & recipient : vecSend)
2621
2640
{
2622
2641
CTxOut txout (recipient.nAmount , recipient.scriptPubKey );
@@ -2633,7 +2652,9 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std
2633
2652
}
2634
2653
}
2635
2654
// Include the fee cost for outputs. Note this is only used for BnB right now
2636
- coin_selection_params.tx_noinputs_size += ::GetSerializeSize (txout, PROTOCOL_VERSION);
2655
+ if (!coin_selection_params.m_subtract_fee_outputs ) {
2656
+ coin_selection_params.tx_noinputs_size += ::GetSerializeSize (txout, PROTOCOL_VERSION);
2657
+ }
2637
2658
2638
2659
if (IsDust (txout, chain ().relayDustFee ()))
2639
2660
{
0 commit comments