Skip to content

Commit 9a822ef

Browse files
committed
Add minimal SandCompactor tests
1 parent b903687 commit 9a822ef

File tree

1 file changed

+90
-0
lines changed

1 file changed

+90
-0
lines changed

src/wallet/test/coinselector_tests.cpp

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1390,6 +1390,96 @@ BOOST_AUTO_TEST_CASE(srd_tests)
13901390
}
13911391
}
13921392

1393+
static util::Result<SelectionResult> SandCompactorHelper(const CAmount& target,
1394+
const CoinSelectionParams& cs_params,
1395+
const node::NodeContext& m_node,
1396+
int max_weight,
1397+
std::function<CoinsResult(CWallet&)> coin_setup)
1398+
{
1399+
std::unique_ptr<CWallet> wallet = NewWallet(m_node);
1400+
CoinEligibilityFilter filter(0, 0, 0); // accept all coins without ancestors
1401+
Groups groups = GroupOutputs(*wallet, coin_setup(*wallet), cs_params, {{filter}})[filter].all_groups;
1402+
1403+
std::vector<OutputGroup> sand_compactor_utxo_pool = cs_params.m_discard_feerate > cs_params.m_effective_feerate ? groups.mixed_group : groups.positive_group;
1404+
return SandCompactor(sand_compactor_utxo_pool, target, cs_params.m_min_change_target, max_weight);
1405+
}
1406+
1407+
BOOST_AUTO_TEST_CASE(sand_compactor_tests)
1408+
{
1409+
// Test SandCompactor:
1410+
// 1) Insufficient funds
1411+
// 2) Exceeded max weight, coin selection always surpasses the max allowed weight.
1412+
// 3) Select coins without surpassing the max weight (some coins surpasses the max allowed weight, some others not)
1413+
1414+
FastRandomContext rand;
1415+
CoinSelectionParams dummy_params{ // Only used to provide the 'avoid_partial' flag.
1416+
rand,
1417+
/*change_output_size=*/34,
1418+
/*change_spend_size=*/68,
1419+
/*min_change_target=*/CENT,
1420+
/*effective_feerate=*/CFeeRate(0),
1421+
/*long_term_feerate=*/CFeeRate(0),
1422+
/*discard_feerate=*/CFeeRate(0),
1423+
/*tx_noinputs_size=*/10 + 34, // static header size + output size
1424+
/*avoid_partial=*/false,
1425+
};
1426+
1427+
{
1428+
// #########################################################
1429+
// 1) Insufficient funds, select all provided coins and fail
1430+
// #########################################################
1431+
CAmount target = 49.5L * COIN;
1432+
int max_weight = 10000; // high enough to not fail for this reason.
1433+
const auto& res = SandCompactorHelper(target, dummy_params, m_node, max_weight, [&](CWallet& wallet) {
1434+
CoinsResult available_coins;
1435+
for (int j = 0; j < 10; ++j) {
1436+
add_coin(available_coins, wallet, CAmount(1 * COIN));
1437+
add_coin(available_coins, wallet, CAmount(2 * COIN));
1438+
}
1439+
return available_coins;
1440+
});
1441+
BOOST_CHECK(!res);
1442+
BOOST_CHECK(util::ErrorString(res).empty()); // empty means "insufficient funds"
1443+
}
1444+
1445+
{
1446+
// ###########################
1447+
// 2) Test max weight exceeded
1448+
// ###########################
1449+
CAmount target = 29.5L * COIN;
1450+
int max_weight = 3000;
1451+
const auto& res = SandCompactorHelper(target, dummy_params, m_node, max_weight, [&](CWallet& wallet) {
1452+
CoinsResult available_coins;
1453+
for (int j = 0; j < 10; ++j) {
1454+
add_coin(available_coins, wallet, CAmount(1 * COIN), CFeeRate(0), 144, false, 0, true);
1455+
add_coin(available_coins, wallet, CAmount(2 * COIN), CFeeRate(0), 144, false, 0, true);
1456+
}
1457+
return available_coins;
1458+
});
1459+
BOOST_CHECK(!res);
1460+
BOOST_CHECK(util::ErrorString(res).original.find("The inputs size exceeds the maximum weight") != std::string::npos);
1461+
}
1462+
1463+
{
1464+
// ################################################################################################################
1465+
// 3) Test selection when some coins surpass the max allowed weight while others not. --> must find a good solution
1466+
// ################################################################################################################
1467+
CAmount target = 25.33L * COIN;
1468+
int max_weight = 10000; // WU
1469+
const auto& res = SandCompactorHelper(target, dummy_params, m_node, max_weight, [&](CWallet& wallet) {
1470+
CoinsResult available_coins;
1471+
for (int j = 0; j < 60; ++j) { // 60 UTXO --> 19,8 BTC total --> 60 × 272 WU = 16320 WU
1472+
add_coin(available_coins, wallet, CAmount(0.33 * COIN), CFeeRate(0), 144, false, 0, true);
1473+
}
1474+
for (int i = 0; i < 10; i++) { // 10 UTXO --> 20 BTC total --> 10 × 272 WU = 2720 WU
1475+
add_coin(available_coins, wallet, CAmount(2 * COIN), CFeeRate(0), 144, false, 0, true);
1476+
}
1477+
return available_coins;
1478+
});
1479+
BOOST_CHECK(res);
1480+
}
1481+
}
1482+
13931483
static util::Result<SelectionResult> select_coins(const CAmount& target, const CoinSelectionParams& cs_params, const CCoinControl& cc, std::function<CoinsResult(CWallet&)> coin_setup, const node::NodeContext& m_node)
13941484
{
13951485
std::unique_ptr<CWallet> wallet = NewWallet(m_node);

0 commit comments

Comments
 (0)