@@ -2234,7 +2234,11 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const CoinEligibil
22342234 if (effective_value > 0 ) {
22352235 group.fee += coin.m_input_bytes < 0 ? 0 : coin_selection_params.effective_fee .GetFee (coin.m_input_bytes );
22362236 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+ }
22382242 ++it;
22392243 } else {
22402244 it = group.Discard (coin);
@@ -2260,6 +2264,7 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const CoinEligibil
22602264bool 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
22612265{
22622266 std::vector<COutput> vCoins (vAvailableCoins);
2267+ CAmount value_to_select = nTargetValue;
22632268
22642269 // coin control -> return all selected outputs (we want all selected to go into the transaction for sure)
22652270 if (coin_control.HasSelected () && !coin_control.fAllowOtherInputs )
@@ -2285,22 +2290,33 @@ bool CWallet::SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAm
22852290 coin_control.ListSelected (vPresetInputs);
22862291 for (const COutPoint& outpoint : vPresetInputs)
22872292 {
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-
22922293 std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find (outpoint.hash );
22932294 if (it != mapWallet.end ())
22942295 {
22952296 const CWalletTx& wtx = it->second ;
22962297 // Clearly invalid input, fail
2297- if (wtx.tx ->vout .size () <= outpoint.n )
2298+ if (wtx.tx ->vout .size () <= outpoint.n ) {
2299+ bnb_used = false ;
22982300 return false ;
2301+ }
22992302 // 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 ;
23032318 return false ; // TODO: Allow non-wallet inputs
2319+ }
23042320 }
23052321
23062322 // remove preset inputs from vCoins
@@ -2329,14 +2345,14 @@ bool CWallet::SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAm
23292345 size_t max_descendants = (size_t )std::max<int64_t >(1 , limit_descendant_count);
23302346 bool fRejectLongChains = gArgs .GetBoolArg (" -walletrejectlongchains" , DEFAULT_WALLET_REJECT_LONG_CHAINS);
23312347
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));
23402356
23412357 // because SelectCoinsMinConf clears the setCoinsRet, we now add the possible inputs to the coinset
23422358 util::insert (setCoinsRet, setPresetCoins);
@@ -2602,7 +2618,8 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std
26022618
26032619 // BnB selector is the only selector used when this is true.
26042620 // 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
26062623 // Start with no fee and loop until there is enough fee
26072624 while (true )
26082625 {
@@ -2616,7 +2633,9 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std
26162633 nValueToSelect += nFeeRet;
26172634
26182635 // 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+ }
26202639 for (const auto & recipient : vecSend)
26212640 {
26222641 CTxOut txout (recipient.nAmount , recipient.scriptPubKey );
@@ -2633,7 +2652,9 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std
26332652 }
26342653 }
26352654 // 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+ }
26372658
26382659 if (IsDust (txout, chain ().relayDustFee ()))
26392660 {
0 commit comments