Skip to content

Commit d97d25d

Browse files
committed
Make cost_of_change part of CoinSelectionParams
1 parent af5867c commit d97d25d

File tree

2 files changed

+23
-16
lines changed

2 files changed

+23
-16
lines changed

src/wallet/wallet.cpp

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2409,17 +2409,10 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const CoinEligibil
24092409
effective_feerate = coin_selection_params.m_effective_feerate;
24102410
}
24112411

2412-
// Cost of change is the cost of creating the change output + cost of spending the change output in the future.
2413-
// For creating the change output now, we use the effective feerate.
2414-
// For spending the change output in the future, we use the discard feerate for now.
2415-
// So cost of change = (change output size * effective feerate) + (size of spending change output * discard feerate)
2416-
const CAmount change_fee = coin_selection_params.m_effective_feerate.GetFee(coin_selection_params.change_output_size);
2417-
const CAmount cost_of_change = coin_selection_params.m_discard_feerate.GetFee(coin_selection_params.change_spend_size) + change_fee;
2418-
24192412
if (coin_selection_params.use_bnb) {
24202413
std::vector<OutputGroup> positive_groups = GroupOutputs(coins, !coin_selection_params.m_avoid_partial_spends, effective_feerate, coin_selection_params.m_long_term_feerate, eligibility_filter, true /* positive_only */);
24212414
bnb_used = true;
2422-
return SelectCoinsBnB(positive_groups, nTargetValue, cost_of_change, setCoinsRet, nValueRet, not_input_fees);
2415+
return SelectCoinsBnB(positive_groups, nTargetValue, coin_selection_params.m_cost_of_change, setCoinsRet, nValueRet, not_input_fees);
24232416
} else {
24242417
// The knapsack solver has some legacy behavior where it will spend dust outputs. We retain this behavior, so don't filter for positive only here.
24252418
// The knapsack solver currently does not use effective values, so we give GroupOutputs feerates of 0 so it sets the effective values to be the same as the real value.
@@ -2885,6 +2878,16 @@ bool CWallet::CreateTransactionInternal(
28852878
CTxOut change_prototype_txout(0, scriptChange);
28862879
coin_selection_params.change_output_size = GetSerializeSize(change_prototype_txout);
28872880

2881+
// Get size of spending the change output
2882+
int change_spend_size = CalculateMaximumSignedInputSize(change_prototype_txout, this);
2883+
// If the wallet doesn't know how to sign change output, assume p2sh-p2wpkh
2884+
// as lower-bound to allow BnB to do it's thing
2885+
if (change_spend_size == -1) {
2886+
coin_selection_params.change_spend_size = DUMMY_NESTED_P2WPKH_INPUT_SIZE;
2887+
} else {
2888+
coin_selection_params.change_spend_size = (size_t)change_spend_size;
2889+
}
2890+
28882891
// Set discard feerate
28892892
coin_selection_params.m_discard_feerate = GetDiscardRate(*this);
28902893

@@ -2907,6 +2910,14 @@ bool CWallet::CreateTransactionInternal(
29072910
cc_temp.m_confirm_target = chain().estimateMaxBlocks();
29082911
coin_selection_params.m_long_term_feerate = GetMinimumFeeRate(*this, cc_temp, nullptr);
29092912

2913+
// Calculate the cost of change
2914+
// Cost of change is the cost of creating the change output + cost of spending the change output in the future.
2915+
// For creating the change output now, we use the effective feerate.
2916+
// For spending the change output in the future, we use the discard feerate for now.
2917+
// So cost of change = (change output size * effective feerate) + (size of spending change output * discard feerate)
2918+
coin_selection_params.m_change_fee = coin_selection_params.m_effective_feerate.GetFee(coin_selection_params.change_output_size);
2919+
coin_selection_params.m_cost_of_change = coin_selection_params.m_discard_feerate.GetFee(coin_selection_params.change_spend_size) + coin_selection_params.m_change_fee;
2920+
29102921
nFeeRet = 0;
29112922
bool pick_new_inputs = true;
29122923
CAmount nValueIn = 0;
@@ -2972,14 +2983,6 @@ bool CWallet::CreateTransactionInternal(
29722983
if (pick_new_inputs) {
29732984
nValueIn = 0;
29742985
setCoins.clear();
2975-
int change_spend_size = CalculateMaximumSignedInputSize(change_prototype_txout, this);
2976-
// If the wallet doesn't know how to sign change output, assume p2sh-p2wpkh
2977-
// as lower-bound to allow BnB to do it's thing
2978-
if (change_spend_size == -1) {
2979-
coin_selection_params.change_spend_size = DUMMY_NESTED_P2WPKH_INPUT_SIZE;
2980-
} else {
2981-
coin_selection_params.change_spend_size = (size_t)change_spend_size;
2982-
}
29832986
if (!SelectCoins(vAvailableCoins, nValueToSelect, setCoins, nValueIn, coin_control, coin_selection_params, bnb_used))
29842987
{
29852988
// If BnB was used, it was the first pass. No longer the first pass and continue loop with knapsack.

src/wallet/wallet.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,10 @@ struct CoinSelectionParams
621621
size_t change_output_size = 0;
622622
/** Size of the input to spend a change output in virtual bytes. */
623623
size_t change_spend_size = 0;
624+
/** Cost of creating the change output. */
625+
CAmount m_change_fee{0};
626+
/** Cost of creating the change output + cost of spending the change output in the future. */
627+
CAmount m_cost_of_change{0};
624628
/** The targeted feerate of the transaction being built. */
625629
CFeeRate m_effective_feerate;
626630
/** The feerate estimate used to estimate an upper bound on what should be sufficient to spend

0 commit comments

Comments
 (0)