diff options
author | Andrew Chow <achow101-github@achow101.com> | 2021-05-07 18:13:40 -0400 |
---|---|---|
committer | Andrew Chow <achow101-github@achow101.com> | 2021-05-13 16:40:56 -0400 |
commit | d97d25d95006725e705635530b27643363d6b2a4 (patch) | |
tree | 8dff6f3264db0f87fa0c303765172cafc982c433 /src/wallet | |
parent | af5867c89688b06173b295b7c32a42845ea455da (diff) | |
download | bitcoin-d97d25d95006725e705635530b27643363d6b2a4.tar.xz |
Make cost_of_change part of CoinSelectionParams
Diffstat (limited to 'src/wallet')
-rw-r--r-- | src/wallet/wallet.cpp | 35 | ||||
-rw-r--r-- | src/wallet/wallet.h | 4 |
2 files changed, 23 insertions, 16 deletions
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index b6dc867dcb..e848145a51 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2409,17 +2409,10 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const CoinEligibil effective_feerate = coin_selection_params.m_effective_feerate; } - // Cost of change is the cost of creating the change output + cost of spending the change output in the future. - // For creating the change output now, we use the effective feerate. - // For spending the change output in the future, we use the discard feerate for now. - // So cost of change = (change output size * effective feerate) + (size of spending change output * discard feerate) - const CAmount change_fee = coin_selection_params.m_effective_feerate.GetFee(coin_selection_params.change_output_size); - const CAmount cost_of_change = coin_selection_params.m_discard_feerate.GetFee(coin_selection_params.change_spend_size) + change_fee; - if (coin_selection_params.use_bnb) { 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 */); bnb_used = true; - return SelectCoinsBnB(positive_groups, nTargetValue, cost_of_change, setCoinsRet, nValueRet, not_input_fees); + return SelectCoinsBnB(positive_groups, nTargetValue, coin_selection_params.m_cost_of_change, setCoinsRet, nValueRet, not_input_fees); } else { // 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. // 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( CTxOut change_prototype_txout(0, scriptChange); coin_selection_params.change_output_size = GetSerializeSize(change_prototype_txout); + // Get size of spending the change output + int change_spend_size = CalculateMaximumSignedInputSize(change_prototype_txout, this); + // If the wallet doesn't know how to sign change output, assume p2sh-p2wpkh + // as lower-bound to allow BnB to do it's thing + if (change_spend_size == -1) { + coin_selection_params.change_spend_size = DUMMY_NESTED_P2WPKH_INPUT_SIZE; + } else { + coin_selection_params.change_spend_size = (size_t)change_spend_size; + } + // Set discard feerate coin_selection_params.m_discard_feerate = GetDiscardRate(*this); @@ -2907,6 +2910,14 @@ bool CWallet::CreateTransactionInternal( cc_temp.m_confirm_target = chain().estimateMaxBlocks(); coin_selection_params.m_long_term_feerate = GetMinimumFeeRate(*this, cc_temp, nullptr); + // Calculate the cost of change + // Cost of change is the cost of creating the change output + cost of spending the change output in the future. + // For creating the change output now, we use the effective feerate. + // For spending the change output in the future, we use the discard feerate for now. + // So cost of change = (change output size * effective feerate) + (size of spending change output * discard feerate) + coin_selection_params.m_change_fee = coin_selection_params.m_effective_feerate.GetFee(coin_selection_params.change_output_size); + 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; + nFeeRet = 0; bool pick_new_inputs = true; CAmount nValueIn = 0; @@ -2972,14 +2983,6 @@ bool CWallet::CreateTransactionInternal( if (pick_new_inputs) { nValueIn = 0; setCoins.clear(); - int change_spend_size = CalculateMaximumSignedInputSize(change_prototype_txout, this); - // If the wallet doesn't know how to sign change output, assume p2sh-p2wpkh - // as lower-bound to allow BnB to do it's thing - if (change_spend_size == -1) { - coin_selection_params.change_spend_size = DUMMY_NESTED_P2WPKH_INPUT_SIZE; - } else { - coin_selection_params.change_spend_size = (size_t)change_spend_size; - } if (!SelectCoins(vAvailableCoins, nValueToSelect, setCoins, nValueIn, coin_control, coin_selection_params, bnb_used)) { // If BnB was used, it was the first pass. No longer the first pass and continue loop with knapsack. diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 5a36d92784..242aea6715 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -621,6 +621,10 @@ struct CoinSelectionParams size_t change_output_size = 0; /** Size of the input to spend a change output in virtual bytes. */ size_t change_spend_size = 0; + /** Cost of creating the change output. */ + CAmount m_change_fee{0}; + /** Cost of creating the change output + cost of spending the change output in the future. */ + CAmount m_cost_of_change{0}; /** The targeted feerate of the transaction being built. */ CFeeRate m_effective_feerate; /** The feerate estimate used to estimate an upper bound on what should be sufficient to spend |