test: coverage for bnb max weight

Basic positive and negative scenarios
This commit is contained in:
furszy 2023-01-19 22:27:48 -03:00
parent 5a2bc45ee0
commit ba9431c505
No known key found for this signature in database
GPG Key ID: 5DD23CCC686AA623

View File

@ -68,7 +68,7 @@ static void add_coin(const CAmount& nValue, int nInput, CoinSet& set, CAmount fe
set.insert(std::make_shared<COutput>(coin)); set.insert(std::make_shared<COutput>(coin));
} }
static void add_coin(CoinsResult& available_coins, CWallet& wallet, const CAmount& nValue, CFeeRate feerate = CFeeRate(0), int nAge = 6*24, bool fIsFromMe = false, int nInput =0, bool spendable = false) static void add_coin(CoinsResult& available_coins, CWallet& wallet, const CAmount& nValue, CFeeRate feerate = CFeeRate(0), int nAge = 6*24, bool fIsFromMe = false, int nInput =0, bool spendable = false, int custom_size = 0)
{ {
CMutableTransaction tx; CMutableTransaction tx;
tx.nLockTime = nextLockTime++; // so all transactions get different hashes tx.nLockTime = nextLockTime++; // so all transactions get different hashes
@ -84,7 +84,7 @@ static void add_coin(CoinsResult& available_coins, CWallet& wallet, const CAmoun
assert(ret.second); assert(ret.second);
CWalletTx& wtx = (*ret.first).second; CWalletTx& wtx = (*ret.first).second;
const auto& txout = wtx.tx->vout.at(nInput); const auto& txout = wtx.tx->vout.at(nInput);
available_coins.Add(OutputType::BECH32, {COutPoint(wtx.GetHash(), nInput), txout, nAge, CalculateMaximumSignedInputSize(txout, &wallet, /*coin_control=*/nullptr), /*spendable=*/ true, /*solvable=*/ true, /*safe=*/ true, wtx.GetTxTime(), fIsFromMe, feerate}); available_coins.Add(OutputType::BECH32, {COutPoint(wtx.GetHash(), nInput), txout, nAge, custom_size == 0 ? CalculateMaximumSignedInputSize(txout, &wallet, /*coin_control=*/nullptr) : custom_size, /*spendable=*/ true, /*solvable=*/ true, /*safe=*/ true, wtx.GetTxTime(), fIsFromMe, feerate});
} }
// Helpers // Helpers
@ -142,13 +142,15 @@ static CAmount make_hard_case(int utxos, std::vector<COutput>& utxo_pool)
return target; return target;
} }
inline std::vector<OutputGroup>& GroupCoins(const std::vector<COutput>& available_coins) inline std::vector<OutputGroup>& GroupCoins(const std::vector<COutput>& available_coins, bool subtract_fee_outputs = false)
{ {
static std::vector<OutputGroup> static_groups; static std::vector<OutputGroup> static_groups;
static_groups.clear(); static_groups.clear();
for (auto& coin : available_coins) { for (auto& coin : available_coins) {
static_groups.emplace_back(); static_groups.emplace_back();
static_groups.back().Insert(std::make_shared<COutput>(coin), /*ancestors=*/ 0, /*descendants=*/ 0); OutputGroup& group = static_groups.back();
group.Insert(std::make_shared<COutput>(coin), /*ancestors=*/ 0, /*descendants=*/ 0);
group.m_subtract_fee_outputs = subtract_fee_outputs;
} }
return static_groups; return static_groups;
} }
@ -411,6 +413,41 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
const auto result13 = SelectCoins(*wallet, available_coins, selected_input, 10 * CENT, coin_control, coin_selection_params_bnb); const auto result13 = SelectCoins(*wallet, available_coins, selected_input, 10 * CENT, coin_control, coin_selection_params_bnb);
BOOST_CHECK(EquivalentResult(expected_result, *result13)); BOOST_CHECK(EquivalentResult(expected_result, *result13));
} }
{
// Test bnb max weight exceeded
// Inputs set [10, 9, 8, 5, 3, 1], Selection Target = 16 and coin 5 exceeding the max weight.
std::unique_ptr<CWallet> wallet = std::make_unique<CWallet>(m_node.chain.get(), "", m_args, CreateMockWalletDatabase());
wallet->LoadWallet();
LOCK(wallet->cs_wallet);
wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
wallet->SetupDescriptorScriptPubKeyMans();
CoinsResult available_coins;
add_coin(available_coins, *wallet, 10 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
add_coin(available_coins, *wallet, 9 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
add_coin(available_coins, *wallet, 8 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
add_coin(available_coins, *wallet, 5 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true, /*custom_size=*/MAX_STANDARD_TX_WEIGHT);
add_coin(available_coins, *wallet, 3 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
add_coin(available_coins, *wallet, 1 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
CAmount selection_target = 16 * CENT;
const auto& no_res = SelectCoinsBnB(GroupCoins(available_coins.All(), /*subtract_fee_outputs*/true),
selection_target, /*cost_of_change=*/0, MAX_STANDARD_TX_WEIGHT);
BOOST_ASSERT(!no_res);
BOOST_CHECK(util::ErrorString(no_res).original.find("The inputs size exceeds the maximum weight") != std::string::npos);
// Now add same coin value with a good size and check that it gets selected
add_coin(available_coins, *wallet, 5 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
const auto& res = SelectCoinsBnB(GroupCoins(available_coins.All(), /*subtract_fee_outputs*/true), selection_target, /*cost_of_change=*/0);
expected_result.Clear();
add_coin(8 * CENT, 2, expected_result);
add_coin(5 * CENT, 2, expected_result);
add_coin(3 * CENT, 2, expected_result);
BOOST_CHECK(EquivalentResult(expected_result, *res));
}
} }
BOOST_AUTO_TEST_CASE(knapsack_solver_test) BOOST_AUTO_TEST_CASE(knapsack_solver_test)