17#include <boost/test/unit_test.hpp>
27#define RANDOM_REPEATS 5
35static void add_coin(
const CAmount& nValue,
int nInput, std::vector<CInputCoin>& set)
38 tx.
vout.resize(nInput + 1);
39 tx.
vout[nInput].nValue = nValue;
46 tx.
vout.resize(nInput + 1);
47 tx.
vout[nInput].nValue = nValue;
55static void add_coin(std::vector<COutput>& coins,
CWallet&
wallet,
const CAmount& nValue,
int nAge = 6*24,
bool fIsFromMe =
false,
int nInput=0,
bool spendable =
false)
57 static int nextLockTime = 0;
60 tx.
vout.resize(nInput + 1);
61 tx.
vout[nInput].nValue = nValue;
77 auto ret =
wallet.mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(txid), std::forward_as_tuple(
MakeTransactionRef(std::move(tx))));
85 COutput output(
wallet, wtx, nInput, nAge,
true ,
true ,
true );
86 coins.push_back(output);
91 std::pair<CoinSet::iterator, CoinSet::iterator> ret = mismatch(a.begin(), a.end(), b.begin());
92 return ret.first == a.end() && ret.second == b.end();
99 for (
int i = 0; i < utxos; ++i) {
100 target += (
CAmount)1 << (utxos+i);
107inline std::vector<OutputGroup>&
GroupCoins(
const std::vector<CInputCoin>& coins)
109 static std::vector<OutputGroup> static_groups;
110 static_groups.clear();
111 for (
auto& coin : coins) {
112 static_groups.emplace_back();
113 static_groups.back().Insert(coin, 0,
true, 0, 0,
false);
115 return static_groups;
118inline std::vector<OutputGroup>&
GroupCoins(
const std::vector<COutput>& coins)
120 static std::vector<OutputGroup> static_groups;
121 static_groups.clear();
122 for (
auto& coin : coins) {
123 static_groups.emplace_back();
126 return static_groups;
135 static std::vector<OutputGroup> static_groups;
137 return static_groups;
144 std::vector<CInputCoin> utxo_pool;
168 actual_selection.clear();
176 actual_selection.clear();
185 actual_selection.clear();
190 actual_selection.clear();
198 actual_selection.clear();
203 actual_selection.clear();
214 actual_selection.clear();
229 actual_selection.clear();
250 for (
int i = 0; i < 50000; ++i) {
262 for (
int i = 5; i <= 20; ++i) {
266 for (
int i = 0; i < 100; ++i) {
280 wallet->SetupDescriptorScriptPubKeyMans();
282 std::vector<COutput> coins;
287 coins.at(0).nInputBytes = 40;
293 coins.at(0).nInputBytes = 40;
304 wallet->SetupDescriptorScriptPubKeyMans();
306 std::vector<COutput> coins;
315 coin_control.
Select(
COutPoint(coins.at(0).tx->GetHash(), coins.at(0).i));
327 wallet->SetupDescriptorScriptPubKeyMans();
329 CoinSet setCoinsRet, setCoinsRet2;
331 std::vector<COutput> coins;
478 for (
int j = 0; j < 20; j++)
529 for (uint16_t j = 0; j < 676; j++)
538 uint16_t returnSize = std::ceil((2000.0 +
MIN_CHANGE)/amt);
539 CAmount returnValue = amt * returnSize;
553 for (
int i2 = 0; i2 < 100; i2++)
608 wallet->SetupDescriptorScriptPubKeyMans();
612 std::vector<COutput> coins;
615 for (
int i = 0; i < 1000; i++)
631 wallet->SetupDescriptorScriptPubKeyMans();
634 std::default_random_engine generator;
635 std::exponential_distribution<double> distribution (100);
639 for (
int i = 0; i < 100; ++i)
641 std::vector<COutput> coins;
645 for (
int j = 0; j < 1000; ++j)
647 CAmount val = distribution(generator)*10000000;
667 BOOST_CHECK_GE(out_value, target);
675 const CAmount change_cost{125};
679 const CAmount excess{in_amt - fee * 2 - target};
708 add_coin(1 *
COIN, 1, selection, fee * 2, fee - fee_diff);
709 add_coin(2 *
COIN, 2, selection, fee * 2, fee - fee_diff);
711 BOOST_CHECK_GT(waste2, waste1);
720 BOOST_CHECK_LT(waste3, waste1);
729 BOOST_CHECK_LT(waste_nochange2, waste_nochange1);
735 const CAmount exact_target{in_amt - fee * 2};
740 const CAmount new_change_cost{fee_diff * 2};
747 const CAmount new_target{in_amt - fee * 2 - fee_diff * 2};
int64_t CAmount
Amount in satoshis (Can be negative)
static constexpr CAmount COIN
The amount of satoshis in one BTC.
void Select(const COutPoint &output)
bool fAllowOtherInputs
If false, allows unselected inputs, but requires all selected inputs be used.
Fee rate in satoshis per kilobyte: CAmount / kB.
An outpoint - a combination of a transaction hash and an index n into its vout.
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
A transaction with a bunch of additional info that only the owner cares about.
CachableAmount m_amounts[AMOUNTTYPE_ENUM_ELEMENTS]
bool m_is_cache_empty
This flag is true if all m_amounts caches are empty.
uint64_t randrange(uint64_t range) noexcept
Generate a random integer in the range [0..range).
std::set< CInputCoin > CoinSet
bool KnapsackSolver(const CAmount &nTargetValue, std::vector< OutputGroup > &groups, std::set< CInputCoin > &setCoinsRet, CAmount &nValueRet)
bool SelectCoinsBnB(std::vector< OutputGroup > &utxo_pool, const CAmount &selection_target, const CAmount &cost_of_change, std::set< CInputCoin > &out_set, CAmount &value_ret)
static void ApproximateBestSubset(const std::vector< OutputGroup > &groups, const CAmount &nTotalLower, const CAmount &nTargetValue, std::vector< char > &vfBest, CAmount &nBest, int iterations=1000)
CAmount GetSelectionWaste(const std::set< CInputCoin > &inputs, CAmount change_cost, CAmount target, bool use_effective_value)
Compute the waste for this result given the cost of change and the opportunity cost of spending these...
static constexpr CAmount MIN_CHANGE
target minimum change amount
static const CoinEligibilityFilter filter_standard(1, 6, 0)
std::vector< OutputGroup > & KnapsackGroupOutputs(const std::vector< COutput > &coins, CWallet &wallet, const CoinEligibilityFilter &filter)
static void add_coin(const CAmount &nValue, int nInput, std::vector< CInputCoin > &set)
static CAmount make_hard_case(int utxos, std::vector< CInputCoin > &utxo_pool)
BOOST_AUTO_TEST_CASE(bnb_search_test)
static const CoinEligibilityFilter filter_confirmed(1, 1, 0)
static bool equal_sets(CoinSet a, CoinSet b)
std::set< CInputCoin > CoinSet
std::vector< OutputGroup > & GroupCoins(const std::vector< CInputCoin > &coins)
static const CoinEligibilityFilter filter_standard_extra(6, 6, 0)
BOOST_AUTO_TEST_SUITE_END()
#define BOOST_FIXTURE_TEST_SUITE(a, b)
#define BOOST_CHECK_EQUAL(v1, v2)
#define BOOST_CHECK(expr)
static CTransactionRef MakeTransactionRef(Tx &&txIn)
static constexpr CAmount CENT
std::vector< OutputGroup > GroupOutputs(const CWallet &wallet, const std::vector< COutput > &outputs, const CoinSelectionParams &coin_sel_params, const CoinEligibilityFilter &filter, bool positive_only)
bool SelectCoins(const CWallet &wallet, const std::vector< COutput > &vAvailableCoins, const CAmount &nTargetValue, std::set< CInputCoin > &setCoinsRet, CAmount &nValueRet, const CCoinControl &coin_control, CoinSelectionParams &coin_selection_params)
Select a set of coins such that nValueRet >= nTargetValue and at least all coins from coin_control ar...
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
std::variant< CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, WitnessUnknown > CTxDestination
A txout script template with a specific destination.
A mutable version of CTransaction.
uint256 GetHash() const
Compute the hash of this CMutableTransaction.
std::vector< CTxOut > vout
void Set(isminefilter filter, CAmount value)
Parameters for filtering which OutputGroups we may use in coin selection.
Parameters for one iteration of Coin Selection.
bool m_subtract_fee_outputs
Indicate that we are subtracting the fee from outputs.
CAmount m_cost_of_change
Cost of creating the change output + cost of spending the change output in the future.
CFeeRate m_effective_feerate
The targeted feerate of the transaction being built.
std::unique_ptr< interfaces::Chain > chain
Testing setup and teardown for wallet.
bool error(const char *fmt, const Args &... args)
std::unique_ptr< WalletDatabase > CreateMockWalletDatabase()
Return object for accessing temporary in-memory database.
@ WALLET_FLAG_DESCRIPTORS
Indicate that this wallet supports DescriptorScriptPubKeyMan.