Skip to content

Commit

Permalink
refactor + document coin selection strategy
Browse files Browse the repository at this point in the history
Co-authored-by: Xekyo <murch@murch.one>
  • Loading branch information
glozow and murchandamus committed Apr 22, 2021
1 parent 3663a03 commit 04817b0
Showing 1 changed file with 41 additions and 8 deletions.
49 changes: 41 additions & 8 deletions src/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2502,15 +2502,48 @@ bool CWallet::SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAm
// explicitly shuffling the outputs before processing
Shuffle(vCoins.begin(), vCoins.end(), FastRandomContext());
}
bool res = value_to_select <= 0 ||
SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(1, 6, 0), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used) ||
SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(1, 1, 0), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used) ||
(m_spend_zero_conf_change && SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(0, 1, 2), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) ||
(m_spend_zero_conf_change && SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(0, 1, std::min((size_t)4, max_ancestors/3), std::min((size_t)4, max_descendants/3)), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) ||
(m_spend_zero_conf_change && SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(0, 1, max_ancestors/2, max_descendants/2), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) ||
(m_spend_zero_conf_change && SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(0, 1, max_ancestors-1, max_descendants-1, true /* include_partial_groups */), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) ||
(m_spend_zero_conf_change && !fRejectLongChains && SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(0, 1, std::numeric_limits<uint64_t>::max(), std::numeric_limits<uint64_t>::max(), true /* include_partial_groups */), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used));

// Attempt to select coins from a pool of available Coins, applying a CoinEligibilityFilter. If an attempt fails, continue with a more permissive filter.
const bool res = [&] {
if (value_to_select <= 0) return true;

// If possible, fund the transaction with confirmed UTXOs only. Prefer at least six confirmations on outputs received from other wallets.
if (SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(1, 6, 0), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) return true;
if (SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(1, 1, 0), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) return true;

// Fall back to using zero confirmation change if we cannot fund the transaction otherwise.
// We never spend unconfirmed outputs received from other wallets.
if (m_spend_zero_conf_change) {
if (SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(0, 1, 2), vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) return true;
if (SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(0, 1, std::min((size_t)4, max_ancestors/3), std::min((size_t)4, max_descendants/3)),
vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) {
return true;
}
if (SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(0, 1, max_ancestors/2, max_descendants/2),
vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) {
return true;
}
// Relax the requirement of spending OutputGroups (groups of UTXOs sent to the same
// address, which are obviously controlled by a single wallet) in their entirety.
if (SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(0, 1, max_ancestors-1, max_descendants-1, true /* include_partial_groups */),
vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) {
return true;
}
// Try with unlimited ancestors/descendants. Note that the tx will still need to
// meet mempool ancestor/descendant policy to be broadcasted.
if (!fRejectLongChains &&
SelectCoinsMinConf(value_to_select,
CoinEligibilityFilter(0, 1, std::numeric_limits<uint64_t>::max(),
std::numeric_limits<uint64_t>::max(),
true /* include_partial_groups */),
vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) {
return true;
}
}
// Coin Selection failed.
return false;
}();

// because SelectCoinsMinConf clears the setCoinsRet, we now add the possible inputs to the coinset
util::insert(setCoinsRet, setPresetCoins);

Expand Down

0 comments on commit 04817b0

Please sign in to comment.