Skip to content

Commit

Permalink
Introduce SelectionResult struct
Browse files Browse the repository at this point in the history
Introduces a SelectionResult struct which contains the set of selected
inputs and the total transaction fee for the transaction. This will be
used by the various SelectCoins* functions. Additionally helpers are
provided to compute the total input value and result comparisons.
  • Loading branch information
achow101 committed Dec 5, 2021
1 parent 94d851d commit 9d1d86d
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 0 deletions.
47 changes: 47 additions & 0 deletions src/wallet/coinselection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -395,3 +395,50 @@ CAmount GetSelectionWaste(const std::set<CInputCoin>& inputs, CAmount change_cos

return waste;
}

void SelectionResult::ComputeAndSetWaste(CAmount change_cost)
{
m_waste = GetSelectionWaste(m_selected_inputs, change_cost, m_target, m_use_effective);
}

CAmount SelectionResult::GetWaste() const
{
Assume(m_waste != std::nullopt);
return *m_waste;
}

CAmount SelectionResult::GetSelectedValue() const
{
return std::accumulate(m_selected_inputs.cbegin(), m_selected_inputs.cend(), CAmount{0}, [](CAmount sum, const auto& coin) { return sum + coin.txout.nValue; });
}

void SelectionResult::Clear()
{
m_selected_inputs.clear();
m_waste.reset();
}

void SelectionResult::AddInput(const OutputGroup& group)
{
util::insert(m_selected_inputs, group.m_outputs);
}

const std::set<CInputCoin>& SelectionResult::GetInputSet() const
{
return m_selected_inputs;
}

std::vector<CInputCoin> SelectionResult::GetShuffledInputVector() const
{
std::vector<CInputCoin> coins(m_selected_inputs.begin(), m_selected_inputs.end());
Shuffle(coins.begin(), coins.end(), FastRandomContext());
return coins;
}

bool SelectionResult::operator<(SelectionResult other) const
{
Assume(m_waste != std::nullopt);
Assume(other.m_waste != std::nullopt);
// 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());
}
35 changes: 35 additions & 0 deletions src/wallet/coinselection.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,41 @@ struct OutputGroup
*/
[[nodiscard]] CAmount GetSelectionWaste(const std::set<CInputCoin>& inputs, CAmount change_cost, CAmount target, bool use_effective_value = true);

struct SelectionResult
{
/** Set of inputs selected by the algorithm to use in the transaction */
std::set<CInputCoin> m_selected_inputs;
/** The target the algorithm selected for. Note that this may not be equal to the recipient amount as it can include non-input fees */
const CAmount m_target;
/** Whether the input values for calculations should be the effective value (true) or normal value (false) */
bool m_use_effective{false};
/** The computed waste */
std::optional<CAmount> m_waste;

explicit SelectionResult(const CAmount target)
: m_target(target) {}

SelectionResult() = delete;

/** Get the sum of the input values */
[[nodiscard]] CAmount GetSelectedValue() const;

void Clear();

void AddInput(const OutputGroup& group);

/** Calculates and stores the waste for this selection via GetSelectionWaste */
void ComputeAndSetWaste(CAmount change_cost);
[[nodiscard]] CAmount GetWaste() const;

/** Get m_selected_inputs */
const std::set<CInputCoin>& GetInputSet() const;
/** Get the vector of CInputCoins that will be used to fill in a CTransaction's vin */
std::vector<CInputCoin> GetShuffledInputVector() const;

bool operator<(SelectionResult other) const;
};

bool SelectCoinsBnB(std::vector<OutputGroup>& utxo_pool, const CAmount& selection_target, const CAmount& cost_of_change, std::set<CInputCoin>& out_set, CAmount& value_ret);

/** Select coins by Single Random Draw. OutputGroups are selected randomly from the eligible
Expand Down

0 comments on commit 9d1d86d

Please sign in to comment.