mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-11-12 06:58:57 +01:00
Merge bitcoin/bitcoin#24091: wallet: Consolidate CInputCoin and COutput
049003fe68coinselection: Remove COutput operators == and != (Andrew Chow)f6c39c6adbcoinselection: Remove CInputCoin (Andrew Chow)70f31f1a81coinselection: Use COutput instead of CInputCoin (Andrew Chow)14fbb57b79coinselection: Add effective value and fees to COutput (Andrew Chow)f0821230b8moveonly: move COutput to coinselection.h (Andrew Chow)42e974e15cwallet: Remove CWallet and CWalletTx from COutput's constructor (Andrew Chow)14d04d5ad1wallet: Replace CWalletTx in COutput with COutPoint and CTxOut (Andrew Chow)0ba4d1916ewallet: Provide input bytes to COutput (Andrew Chow)d51f27d3bbwallet: Store whether a COutput is from the wallet (Andrew Chow)b799814bbdwallet: Store tx time in COutput (Andrew Chow)46022953eewallet: Remove use_max_sig default value (Andrew Chow)10379f007fscripted-diff: Rename COutput member variables (Andrew Chow)c7c64db41ewallet: cleanup COutput constructor (Andrew Chow) Pull request description: While working on coin selection code, it occurred to me that `CInputCoin` is really a subset of `COutput` and the conversion of a `COutput` to a `CInputCoin` does not appear to be all that useful. So this PR adds fields that are present in `CInputCoin` to `COutput` and replaces the usage of `CInputCoin` with `COutput`. `COutput` is also moved to coinselection.h. As part of this move, the usage of `CWalletTx` is removed from `COutput`. It is instead replaced by storing a `COutPoint` and the `CTxOut` rather than the entire `CWalletTx` as coin selection does not really need the full `CWalletTx`. The `CWalletTx` was only used for figuring out whether the transaction containing the output was from the current wallet, and for the transaction's time. These are now parameters to `COutput`'s constructor. ACKs for top commit: ryanofsky: Code review ACK049003fe68, just adding comments and removing == operators since last review w0xlt: reACK049003fXekyo: reACK049003fe68Tree-SHA512: 048b4cd620a0415e1d9fe8597257ee4bc64656566e1d28a9bdd147d6d72dc87c3f34a3339fa9ab6acf42c388df7901fc4ee900ccaabc3de790ffad162b544c15
This commit is contained in:
@@ -50,8 +50,8 @@ struct {
|
||||
* The Branch and Bound algorithm is described in detail in Murch's Master Thesis:
|
||||
* https://murch.one/wp-content/uploads/2016/11/erhardt2016coinselection.pdf
|
||||
*
|
||||
* @param const std::vector<CInputCoin>& utxo_pool The set of UTXOs that we are choosing from.
|
||||
* These UTXOs will be sorted in descending order by effective value and the CInputCoins'
|
||||
* @param const std::vector<OutputGroup>& utxo_pool The set of UTXO groups that we are choosing from.
|
||||
* These UTXO groups will be sorted in descending order by effective value and the OutputGroups'
|
||||
* values are their effective values.
|
||||
* @param const CAmount& selection_target This is the value that we want to select. It is the lower
|
||||
* bound of the range.
|
||||
@@ -309,29 +309,29 @@ std::optional<SelectionResult> KnapsackSolver(std::vector<OutputGroup>& groups,
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
void OutputGroup::Insert(const CInputCoin& output, int depth, bool from_me, size_t ancestors, size_t descendants, bool positive_only) {
|
||||
void OutputGroup::Insert(const COutput& output, size_t ancestors, size_t descendants, bool positive_only) {
|
||||
// Compute the effective value first
|
||||
const CAmount coin_fee = output.m_input_bytes < 0 ? 0 : m_effective_feerate.GetFee(output.m_input_bytes);
|
||||
const CAmount coin_fee = output.input_bytes < 0 ? 0 : m_effective_feerate.GetFee(output.input_bytes);
|
||||
const CAmount ev = output.txout.nValue - coin_fee;
|
||||
|
||||
// Filter for positive only here before adding the coin
|
||||
if (positive_only && ev <= 0) return;
|
||||
|
||||
m_outputs.push_back(output);
|
||||
CInputCoin& coin = m_outputs.back();
|
||||
COutput& coin = m_outputs.back();
|
||||
|
||||
coin.m_fee = coin_fee;
|
||||
fee += coin.m_fee;
|
||||
coin.fee = coin_fee;
|
||||
fee += coin.fee;
|
||||
|
||||
coin.m_long_term_fee = coin.m_input_bytes < 0 ? 0 : m_long_term_feerate.GetFee(coin.m_input_bytes);
|
||||
long_term_fee += coin.m_long_term_fee;
|
||||
coin.long_term_fee = coin.input_bytes < 0 ? 0 : m_long_term_feerate.GetFee(coin.input_bytes);
|
||||
long_term_fee += coin.long_term_fee;
|
||||
|
||||
coin.effective_value = ev;
|
||||
effective_value += coin.effective_value;
|
||||
|
||||
m_from_me &= from_me;
|
||||
m_value += output.txout.nValue;
|
||||
m_depth = std::min(m_depth, depth);
|
||||
m_from_me &= coin.from_me;
|
||||
m_value += coin.txout.nValue;
|
||||
m_depth = std::min(m_depth, coin.depth);
|
||||
// ancestors here express the number of ancestors the new coin will end up having, which is
|
||||
// the sum, rather than the max; this will overestimate in the cases where multiple inputs
|
||||
// have common ancestors
|
||||
@@ -353,7 +353,7 @@ CAmount OutputGroup::GetSelectionAmount() const
|
||||
return m_subtract_fee_outputs ? m_value : effective_value;
|
||||
}
|
||||
|
||||
CAmount GetSelectionWaste(const std::set<CInputCoin>& inputs, CAmount change_cost, CAmount target, bool use_effective_value)
|
||||
CAmount GetSelectionWaste(const std::set<COutput>& inputs, CAmount change_cost, CAmount target, bool use_effective_value)
|
||||
{
|
||||
// This function should not be called with empty inputs as that would mean the selection failed
|
||||
assert(!inputs.empty());
|
||||
@@ -361,8 +361,8 @@ CAmount GetSelectionWaste(const std::set<CInputCoin>& inputs, CAmount change_cos
|
||||
// Always consider the cost of spending an input now vs in the future.
|
||||
CAmount waste = 0;
|
||||
CAmount selected_effective_value = 0;
|
||||
for (const CInputCoin& coin : inputs) {
|
||||
waste += coin.m_fee - coin.m_long_term_fee;
|
||||
for (const COutput& coin : inputs) {
|
||||
waste += coin.fee - coin.long_term_fee;
|
||||
selected_effective_value += use_effective_value ? coin.effective_value : coin.txout.nValue;
|
||||
}
|
||||
|
||||
@@ -407,14 +407,14 @@ void SelectionResult::AddInput(const OutputGroup& group)
|
||||
m_use_effective = !group.m_subtract_fee_outputs;
|
||||
}
|
||||
|
||||
const std::set<CInputCoin>& SelectionResult::GetInputSet() const
|
||||
const std::set<COutput>& SelectionResult::GetInputSet() const
|
||||
{
|
||||
return m_selected_inputs;
|
||||
}
|
||||
|
||||
std::vector<CInputCoin> SelectionResult::GetShuffledInputVector() const
|
||||
std::vector<COutput> SelectionResult::GetShuffledInputVector() const
|
||||
{
|
||||
std::vector<CInputCoin> coins(m_selected_inputs.begin(), m_selected_inputs.end());
|
||||
std::vector<COutput> coins(m_selected_inputs.begin(), m_selected_inputs.end());
|
||||
Shuffle(coins.begin(), coins.end(), FastRandomContext());
|
||||
return coins;
|
||||
}
|
||||
@@ -426,4 +426,9 @@ bool SelectionResult::operator<(SelectionResult other) const
|
||||
// As this operator is only used in std::min_element, we want the result that has more inputs when waste are equal.
|
||||
return *m_waste < *other.m_waste || (*m_waste == *other.m_waste && m_selected_inputs.size() > other.m_selected_inputs.size());
|
||||
}
|
||||
|
||||
std::string COutput::ToString() const
|
||||
{
|
||||
return strprintf("COutput(%s, %d, %d) [%s]", outpoint.hash.ToString(), outpoint.n, depth, FormatMoney(txout.nValue));
|
||||
}
|
||||
} // namespace wallet
|
||||
|
||||
Reference in New Issue
Block a user