Skip to content

Commit 99b399a

Browse files
committed
Move fee setting of OutputGroup to Insert
OutputGroup will handle the fee and effective value computations inside of Insert. It now needs to take the effective feerate and long term feerates as arguments to its constructor.
1 parent 6148a8a commit 99b399a

File tree

4 files changed

+33
-38
lines changed

4 files changed

+33
-38
lines changed

src/wallet/coinselection.cpp

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,16 @@ bool KnapsackSolver(const CAmount& nTargetValue, std::vector<OutputGroup>& group
302302

303303
void OutputGroup::Insert(const CInputCoin& output, int depth, bool from_me, size_t ancestors, size_t descendants) {
304304
m_outputs.push_back(output);
305+
CInputCoin& coin = m_outputs.back();
306+
coin.m_fee = coin.m_input_bytes < 0 ? 0 : m_effective_feerate.GetFee(coin.m_input_bytes);
307+
fee += coin.m_fee;
308+
309+
coin.m_long_term_fee = coin.m_input_bytes < 0 ? 0 : m_long_term_feerate.GetFee(coin.m_input_bytes);
310+
long_term_fee += coin.m_long_term_fee;
311+
312+
coin.effective_value = coin.txout.nValue - coin.m_fee;
313+
effective_value += coin.effective_value;
314+
305315
m_from_me &= from_me;
306316
m_value += output.txout.nValue;
307317
m_depth = std::min(m_depth, depth);
@@ -312,9 +322,6 @@ void OutputGroup::Insert(const CInputCoin& output, int depth, bool from_me, size
312322
// descendants is the count as seen from the top ancestor, not the descendants as seen from the
313323
// coin itself; thus, this value is counted as the max, not the sum
314324
m_descendants = std::max(m_descendants, descendants);
315-
effective_value += output.effective_value;
316-
fee += output.m_fee;
317-
long_term_fee += output.m_long_term_fee;
318325
}
319326

320327
std::vector<CInputCoin>::iterator OutputGroup::Discard(const CInputCoin& output) {
@@ -335,23 +342,6 @@ bool OutputGroup::EligibleForSpending(const CoinEligibilityFilter& eligibility_f
335342
&& m_descendants <= eligibility_filter.max_descendants;
336343
}
337344

338-
void OutputGroup::SetFees(const CFeeRate effective_feerate, const CFeeRate long_term_feerate)
339-
{
340-
fee = 0;
341-
long_term_fee = 0;
342-
effective_value = 0;
343-
for (CInputCoin& coin : m_outputs) {
344-
coin.m_fee = coin.m_input_bytes < 0 ? 0 : effective_feerate.GetFee(coin.m_input_bytes);
345-
fee += coin.m_fee;
346-
347-
coin.m_long_term_fee = coin.m_input_bytes < 0 ? 0 : long_term_feerate.GetFee(coin.m_input_bytes);
348-
long_term_fee += coin.m_long_term_fee;
349-
350-
coin.effective_value = coin.txout.nValue - coin.m_fee;
351-
effective_value += coin.effective_value;
352-
}
353-
}
354-
355345
OutputGroup OutputGroup::GetPositiveOnlyGroup()
356346
{
357347
OutputGroup group(*this);

src/wallet/coinselection.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,10 @@
66
#define BITCOIN_WALLET_COINSELECTION_H
77

88
#include <amount.h>
9+
#include <policy/feerate.h>
910
#include <primitives/transaction.h>
1011
#include <random.h>
1112

12-
class CFeeRate;
13-
1413
//! target minimum change amount
1514
static constexpr CAmount MIN_CHANGE{COIN / 100};
1615
//! final minimum change amount after paying for fees
@@ -78,15 +77,20 @@ struct OutputGroup
7877
size_t m_descendants{0};
7978
CAmount effective_value{0};
8079
CAmount fee{0};
80+
CFeeRate m_effective_feerate{0};
8181
CAmount long_term_fee{0};
82+
CFeeRate m_long_term_feerate{0};
8283

8384
OutputGroup() {}
85+
OutputGroup(const CFeeRate& effective_feerate, const CFeeRate& long_term_feerate) :
86+
m_effective_feerate(effective_feerate),
87+
m_long_term_feerate(long_term_feerate)
88+
{}
89+
8490
void Insert(const CInputCoin& output, int depth, bool from_me, size_t ancestors, size_t descendants);
8591
std::vector<CInputCoin>::iterator Discard(const CInputCoin& output);
8692
bool EligibleForSpending(const CoinEligibilityFilter& eligibility_filter) const;
8793

88-
//! Update the OutputGroup's fee, long_term_fee, and effective_value based on the given feerates
89-
void SetFees(const CFeeRate effective_feerate, const CFeeRate long_term_feerate);
9094
OutputGroup GetPositiveOnlyGroup();
9195
};
9296

src/wallet/wallet.cpp

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2381,7 +2381,14 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const CoinEligibil
23812381
temp.m_confirm_target = 1008;
23822382
CFeeRate long_term_feerate = GetMinimumFeeRate(*this, temp, &feeCalc);
23832383

2384-
std::vector<OutputGroup> groups = GroupOutputs(coins, !coin_selection_params.m_avoid_partial_spends, eligibility_filter.max_ancestors);
2384+
// Get the feerate for effective value.
2385+
// When subtracting the fee from the outputs, we want the effective feerate to be 0
2386+
CFeeRate effective_feerate{0};
2387+
if (!coin_selection_params.m_subtract_fee_outputs) {
2388+
effective_feerate = coin_selection_params.effective_fee;
2389+
}
2390+
2391+
std::vector<OutputGroup> groups = GroupOutputs(coins, !coin_selection_params.m_avoid_partial_spends, eligibility_filter.max_ancestors, effective_feerate, long_term_feerate);
23852392

23862393
// Calculate cost of change
23872394
CAmount cost_of_change = GetDiscardRate(*this).GetFee(coin_selection_params.change_spend_size) + coin_selection_params.effective_fee.GetFee(coin_selection_params.change_output_size);
@@ -2390,13 +2397,6 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const CoinEligibil
23902397
for (OutputGroup& group : groups) {
23912398
if (!group.EligibleForSpending(eligibility_filter)) continue;
23922399

2393-
if (coin_selection_params.m_subtract_fee_outputs) {
2394-
// Set the effective feerate to 0 as we don't want to use the effective value since the fees will be deducted from the output
2395-
group.SetFees(CFeeRate(0) /* effective_feerate */, long_term_feerate);
2396-
} else {
2397-
group.SetFees(coin_selection_params.effective_fee, long_term_feerate);
2398-
}
2399-
24002400
OutputGroup pos_group = group.GetPositiveOnlyGroup();
24012401
if (pos_group.effective_value > 0) utxo_pool.push_back(pos_group);
24022402
}
@@ -2405,7 +2405,7 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const CoinEligibil
24052405
bnb_used = true;
24062406
return SelectCoinsBnB(utxo_pool, nTargetValue, cost_of_change, setCoinsRet, nValueRet, not_input_fees);
24072407
} else {
2408-
std::vector<OutputGroup> groups = GroupOutputs(coins, !coin_selection_params.m_avoid_partial_spends, eligibility_filter.max_ancestors);
2408+
std::vector<OutputGroup> groups = GroupOutputs(coins, !coin_selection_params.m_avoid_partial_spends, eligibility_filter.max_ancestors, CFeeRate(0), CFeeRate(0));
24092409

24102410
// Filter by the min conf specs and add to utxo_pool
24112411
for (const OutputGroup& group : groups) {
@@ -4206,7 +4206,7 @@ bool CWalletTx::IsImmatureCoinBase() const
42064206
return GetBlocksToMaturity() > 0;
42074207
}
42084208

4209-
std::vector<OutputGroup> CWallet::GroupOutputs(const std::vector<COutput>& outputs, bool single_coin, const size_t max_ancestors) const {
4209+
std::vector<OutputGroup> CWallet::GroupOutputs(const std::vector<COutput>& outputs, bool single_coin, const size_t max_ancestors, const CFeeRate& effective_feerate, const CFeeRate& long_term_feerate) const {
42104210
std::vector<OutputGroup> groups;
42114211
std::map<CTxDestination, OutputGroup> gmap;
42124212
std::set<CTxDestination> full_groups;
@@ -4228,15 +4228,16 @@ std::vector<OutputGroup> CWallet::GroupOutputs(const std::vector<COutput>& outpu
42284228
// high amount of fees.
42294229
if (it->second.m_outputs.size() >= OUTPUT_GROUP_MAX_ENTRIES) {
42304230
groups.push_back(it->second);
4231-
it->second = OutputGroup{};
4231+
it->second = OutputGroup{effective_feerate, long_term_feerate};
42324232
full_groups.insert(dst);
42334233
}
42344234
it->second.Insert(input_coin, output.nDepth, output.tx->IsFromMe(ISMINE_ALL), ancestors, descendants);
42354235
} else {
4236-
gmap[dst].Insert(input_coin, output.nDepth, output.tx->IsFromMe(ISMINE_ALL), ancestors, descendants);
4236+
auto ins = gmap.emplace(dst, OutputGroup{effective_feerate, long_term_feerate});
4237+
ins.first->second.Insert(input_coin, output.nDepth, output.tx->IsFromMe(ISMINE_ALL), ancestors, descendants);
42374238
}
42384239
} else {
4239-
groups.emplace_back();
4240+
groups.emplace_back(effective_feerate, long_term_feerate);
42404241
groups.back().Insert(input_coin, output.nDepth, output.tx->IsFromMe(ISMINE_ALL), ancestors, descendants);
42414242
}
42424243
}

src/wallet/wallet.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -841,7 +841,7 @@ class CWallet final : public WalletStorage, public interfaces::Chain::Notificati
841841
bool IsSpentKey(const uint256& hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
842842
void SetSpentKeyState(WalletBatch& batch, const uint256& hash, unsigned int n, bool used, std::set<CTxDestination>& tx_destinations) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
843843

844-
std::vector<OutputGroup> GroupOutputs(const std::vector<COutput>& outputs, bool single_coin, const size_t max_ancestors) const;
844+
std::vector<OutputGroup> GroupOutputs(const std::vector<COutput>& outputs, bool single_coin, const size_t max_ancestors, const CFeeRate& effective_feerate, const CFeeRate& long_term_feerate) const;
845845

846846
bool IsLockedCoin(uint256 hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
847847
void LockCoin(const COutPoint& output) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);

0 commit comments

Comments
 (0)