0
0
Fork 0
mirror of https://github.com/bitcoin/bitcoin.git synced 2025-02-03 09:56:38 -05:00

refactor: coinselector_tests, unify wallet creation code

same lines of code repeated across the entire file over and over.
This commit is contained in:
furszy 2023-01-19 22:45:48 -03:00
parent ba9431c505
commit 25ab14712b
No known key found for this signature in database
GPG key ID: 5DD23CCC686AA623

View file

@ -174,6 +174,16 @@ inline std::vector<OutputGroup>& KnapsackGroupOutputs(const CoinsResult& availab
return static_groups.all_groups.mixed_group;
}
static std::unique_ptr<CWallet> NewWallet(const node::NodeContext& m_node, const std::string& wallet_name = "")
{
std::unique_ptr<CWallet> wallet = std::make_unique<CWallet>(m_node.chain.get(), wallet_name, CreateMockWalletDatabase());
BOOST_CHECK(wallet->LoadWallet() == DBErrors::LOAD_OK);
LOCK(wallet->cs_wallet);
wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
wallet->SetupDescriptorScriptPubKeyMans();
return wallet;
}
// Branch and bound coin selection tests
BOOST_AUTO_TEST_CASE(bnb_search_test)
{
@ -310,11 +320,7 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
coin_selection_params_bnb.m_subtract_fee_outputs = true;
{
std::unique_ptr<CWallet> wallet = std::make_unique<CWallet>(m_node.chain.get(), "", CreateMockWalletDatabase());
wallet->LoadWallet();
LOCK(wallet->cs_wallet);
wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
wallet->SetupDescriptorScriptPubKeyMans();
std::unique_ptr<CWallet> wallet = NewWallet(m_node);
CoinsResult available_coins;
@ -332,11 +338,7 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
}
{
std::unique_ptr<CWallet> wallet = std::make_unique<CWallet>(m_node.chain.get(), "", CreateMockWalletDatabase());
wallet->LoadWallet();
LOCK(wallet->cs_wallet);
wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
wallet->SetupDescriptorScriptPubKeyMans();
std::unique_ptr<CWallet> wallet = NewWallet(m_node);
CoinsResult available_coins;
@ -351,15 +353,13 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
selected_input.Insert(select_coin, coin_selection_params_bnb.m_subtract_fee_outputs);
available_coins.Erase({available_coins.coins[OutputType::BECH32].begin()->outpoint});
coin_selection_params_bnb.m_effective_feerate = CFeeRate(0);
LOCK(wallet->cs_wallet);
const auto result10 = SelectCoins(*wallet, available_coins, selected_input, 10 * CENT, coin_control, coin_selection_params_bnb);
BOOST_CHECK(result10);
}
{
std::unique_ptr<CWallet> wallet = std::make_unique<CWallet>(m_node.chain.get(), "", CreateMockWalletDatabase());
wallet->LoadWallet();
LOCK(wallet->cs_wallet);
wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
wallet->SetupDescriptorScriptPubKeyMans();
std::unique_ptr<CWallet> wallet = NewWallet(m_node);
LOCK(wallet->cs_wallet); // Every 'SelectCoins' call requires it
CoinsResult available_coins;
@ -418,11 +418,7 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
// 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();
std::unique_ptr<CWallet> wallet = NewWallet(m_node);
CoinsResult available_coins;
add_coin(available_coins, *wallet, 10 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
@ -455,11 +451,7 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test)
FastRandomContext rand{};
const auto temp1{[&rand](std::vector<OutputGroup>& g, const CAmount& v, CAmount c) { return KnapsackSolver(g, v, c, rand); }};
const auto KnapsackSolver{temp1};
std::unique_ptr<CWallet> wallet = std::make_unique<CWallet>(m_node.chain.get(), "", CreateMockWalletDatabase());
wallet->LoadWallet();
LOCK(wallet->cs_wallet);
wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
wallet->SetupDescriptorScriptPubKeyMans();
std::unique_ptr<CWallet> wallet = NewWallet(m_node);
CoinsResult available_coins;
@ -765,11 +757,7 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test)
BOOST_AUTO_TEST_CASE(ApproximateBestSubset)
{
FastRandomContext rand{};
std::unique_ptr<CWallet> wallet = std::make_unique<CWallet>(m_node.chain.get(), "", CreateMockWalletDatabase());
wallet->LoadWallet();
LOCK(wallet->cs_wallet);
wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
wallet->SetupDescriptorScriptPubKeyMans();
std::unique_ptr<CWallet> wallet = NewWallet(m_node);
CoinsResult available_coins;
@ -787,11 +775,8 @@ BOOST_AUTO_TEST_CASE(ApproximateBestSubset)
// Tests that with the ideal conditions, the coin selector will always be able to find a solution that can pay the target value
BOOST_AUTO_TEST_CASE(SelectCoins_test)
{
std::unique_ptr<CWallet> wallet = std::make_unique<CWallet>(m_node.chain.get(), "", CreateMockWalletDatabase());
wallet->LoadWallet();
LOCK(wallet->cs_wallet);
wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
wallet->SetupDescriptorScriptPubKeyMans();
std::unique_ptr<CWallet> wallet = NewWallet(m_node);
LOCK(wallet->cs_wallet); // Every 'SelectCoins' call requires it
// Random generator stuff
std::default_random_engine generator;
@ -979,12 +964,7 @@ static util::Result<SelectionResult> SelectCoinsSRD(const CAmount& target,
int max_weight,
std::function<CoinsResult(CWallet&)> coin_setup)
{
std::unique_ptr<CWallet> wallet = std::make_unique<CWallet>(m_node.chain.get(), "", CreateMockWalletDatabase());
wallet->LoadWallet();
LOCK(wallet->cs_wallet);
wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
wallet->SetupDescriptorScriptPubKeyMans();
std::unique_ptr<CWallet> wallet = NewWallet(m_node);
CoinEligibilityFilter filter(0, 0, 0); // accept all coins without ancestors
Groups group = GroupOutputs(*wallet, coin_setup(*wallet), cs_params, {{filter}})[filter].all_groups;
return SelectCoinsSRD(group.positive_group, target, cs_params.rng_fast, max_weight);
@ -1066,16 +1046,12 @@ BOOST_AUTO_TEST_CASE(srd_tests)
}
}
static util::Result<SelectionResult> select_coins(const CAmount& target, const CoinSelectionParams& cs_params, const CCoinControl& cc, std::function<CoinsResult(CWallet&)> coin_setup, interfaces::Chain* chain)
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)
{
std::unique_ptr<CWallet> wallet = std::make_unique<CWallet>(chain, "", CreateMockWalletDatabase());
wallet->LoadWallet();
LOCK(wallet->cs_wallet);
wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
wallet->SetupDescriptorScriptPubKeyMans();
std::unique_ptr<CWallet> wallet = NewWallet(m_node);
auto available_coins = coin_setup(*wallet);
LOCK(wallet->cs_wallet);
auto result = SelectCoins(*wallet, available_coins, /*pre_set_inputs=*/ {}, target, cc, cs_params);
if (result) {
const auto signedTxSize = 10 + 34 + 68 * result->GetInputSet().size(); // static header size + output size + inputs size (P2WPKH)
@ -1109,8 +1085,6 @@ BOOST_AUTO_TEST_CASE(check_max_weight)
/*avoid_partial=*/false,
};
auto chain{m_node.chain.get()};
{
// Scenario 1:
// The actor starts with 1x 50.0 BTC and 1515x 0.033 BTC (~100.0 BTC total) unspent outputs
@ -1129,7 +1103,7 @@ BOOST_AUTO_TEST_CASE(check_max_weight)
add_coin(available_coins, wallet, CAmount(50 * COIN), CFeeRate(0), 144, false, 0, true);
return available_coins;
},
chain);
m_node);
BOOST_CHECK(result);
// Verify that only the 50 BTC UTXO was selected
@ -1157,7 +1131,7 @@ BOOST_AUTO_TEST_CASE(check_max_weight)
}
return available_coins;
},
chain);
m_node);
BOOST_CHECK(has_coin(result->GetInputSet(), CAmount(0.0625 * COIN)));
BOOST_CHECK(has_coin(result->GetInputSet(), CAmount(0.025 * COIN)));
@ -1178,7 +1152,7 @@ BOOST_AUTO_TEST_CASE(check_max_weight)
}
return available_coins;
},
chain);
m_node);
// No results
// 1515 inputs * 68 bytes = 103,020 bytes
@ -1193,20 +1167,11 @@ BOOST_AUTO_TEST_CASE(SelectCoins_effective_value_test)
// This test creates a coin whose value is higher than the target but whose effective value is lower than the target.
// The coin is selected using coin control, with m_allow_other_inputs = false. SelectCoins should fail due to insufficient funds.
std::unique_ptr<CWallet> wallet = std::make_unique<CWallet>(m_node.chain.get(), "", CreateMockWalletDatabase());
wallet->LoadWallet();
LOCK(wallet->cs_wallet);
wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
wallet->SetupDescriptorScriptPubKeyMans();
std::unique_ptr<CWallet> wallet = NewWallet(m_node);
CoinsResult available_coins;
{
std::unique_ptr<CWallet> dummyWallet = std::make_unique<CWallet>(m_node.chain.get(), "dummy", CreateMockWalletDatabase());
dummyWallet->LoadWallet();
LOCK(dummyWallet->cs_wallet);
dummyWallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
dummyWallet->SetupDescriptorScriptPubKeyMans();
std::unique_ptr<CWallet> dummyWallet = NewWallet(m_node, /*wallet_name=*/"dummy");
add_coin(available_coins, *dummyWallet, 100000); // 0.001 BTC
}
@ -1230,6 +1195,7 @@ BOOST_AUTO_TEST_CASE(SelectCoins_effective_value_test)
cc.SetInputWeight(output.outpoint, 148);
cc.SelectExternal(output.outpoint, output.txout);
LOCK(wallet->cs_wallet);
const auto preset_inputs = *Assert(FetchSelectedInputs(*wallet, cc, cs_params));
available_coins.Erase({available_coins.coins[OutputType::BECH32].begin()->outpoint});
@ -1242,11 +1208,7 @@ BOOST_FIXTURE_TEST_CASE(wallet_coinsresult_test, BasicTestingSetup)
// Test case to verify CoinsResult object sanity.
CoinsResult available_coins;
{
std::unique_ptr<CWallet> dummyWallet = std::make_unique<CWallet>(m_node.chain.get(), "dummy", CreateMockWalletDatabase());
BOOST_CHECK_EQUAL(dummyWallet->LoadWallet(), DBErrors::LOAD_OK);
LOCK(dummyWallet->cs_wallet);
dummyWallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
dummyWallet->SetupDescriptorScriptPubKeyMans();
std::unique_ptr<CWallet> dummyWallet = NewWallet(m_node, /*wallet_name=*/"dummy");
// Add some coins to 'available_coins'
for (int i=0; i<10; i++) {