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:
parent
ba9431c505
commit
25ab14712b
1 changed files with 31 additions and 69 deletions
|
@ -174,6 +174,16 @@ inline std::vector<OutputGroup>& KnapsackGroupOutputs(const CoinsResult& availab
|
||||||
return static_groups.all_groups.mixed_group;
|
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
|
// Branch and bound coin selection tests
|
||||||
BOOST_AUTO_TEST_CASE(bnb_search_test)
|
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;
|
coin_selection_params_bnb.m_subtract_fee_outputs = true;
|
||||||
|
|
||||||
{
|
{
|
||||||
std::unique_ptr<CWallet> wallet = std::make_unique<CWallet>(m_node.chain.get(), "", CreateMockWalletDatabase());
|
std::unique_ptr<CWallet> wallet = NewWallet(m_node);
|
||||||
wallet->LoadWallet();
|
|
||||||
LOCK(wallet->cs_wallet);
|
|
||||||
wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
|
|
||||||
wallet->SetupDescriptorScriptPubKeyMans();
|
|
||||||
|
|
||||||
CoinsResult available_coins;
|
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());
|
std::unique_ptr<CWallet> wallet = NewWallet(m_node);
|
||||||
wallet->LoadWallet();
|
|
||||||
LOCK(wallet->cs_wallet);
|
|
||||||
wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
|
|
||||||
wallet->SetupDescriptorScriptPubKeyMans();
|
|
||||||
|
|
||||||
CoinsResult available_coins;
|
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);
|
selected_input.Insert(select_coin, coin_selection_params_bnb.m_subtract_fee_outputs);
|
||||||
available_coins.Erase({available_coins.coins[OutputType::BECH32].begin()->outpoint});
|
available_coins.Erase({available_coins.coins[OutputType::BECH32].begin()->outpoint});
|
||||||
coin_selection_params_bnb.m_effective_feerate = CFeeRate(0);
|
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);
|
const auto result10 = SelectCoins(*wallet, available_coins, selected_input, 10 * CENT, coin_control, coin_selection_params_bnb);
|
||||||
BOOST_CHECK(result10);
|
BOOST_CHECK(result10);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::unique_ptr<CWallet> wallet = std::make_unique<CWallet>(m_node.chain.get(), "", CreateMockWalletDatabase());
|
std::unique_ptr<CWallet> wallet = NewWallet(m_node);
|
||||||
wallet->LoadWallet();
|
LOCK(wallet->cs_wallet); // Every 'SelectCoins' call requires it
|
||||||
LOCK(wallet->cs_wallet);
|
|
||||||
wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
|
|
||||||
wallet->SetupDescriptorScriptPubKeyMans();
|
|
||||||
|
|
||||||
CoinsResult available_coins;
|
CoinsResult available_coins;
|
||||||
|
|
||||||
|
@ -418,11 +418,7 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
|
||||||
// Test bnb max weight exceeded
|
// Test bnb max weight exceeded
|
||||||
// Inputs set [10, 9, 8, 5, 3, 1], Selection Target = 16 and coin 5 exceeding the max weight.
|
// 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());
|
std::unique_ptr<CWallet> wallet = NewWallet(m_node);
|
||||||
wallet->LoadWallet();
|
|
||||||
LOCK(wallet->cs_wallet);
|
|
||||||
wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
|
|
||||||
wallet->SetupDescriptorScriptPubKeyMans();
|
|
||||||
|
|
||||||
CoinsResult available_coins;
|
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, 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{};
|
FastRandomContext rand{};
|
||||||
const auto temp1{[&rand](std::vector<OutputGroup>& g, const CAmount& v, CAmount c) { return KnapsackSolver(g, v, c, rand); }};
|
const auto temp1{[&rand](std::vector<OutputGroup>& g, const CAmount& v, CAmount c) { return KnapsackSolver(g, v, c, rand); }};
|
||||||
const auto KnapsackSolver{temp1};
|
const auto KnapsackSolver{temp1};
|
||||||
std::unique_ptr<CWallet> wallet = std::make_unique<CWallet>(m_node.chain.get(), "", CreateMockWalletDatabase());
|
std::unique_ptr<CWallet> wallet = NewWallet(m_node);
|
||||||
wallet->LoadWallet();
|
|
||||||
LOCK(wallet->cs_wallet);
|
|
||||||
wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
|
|
||||||
wallet->SetupDescriptorScriptPubKeyMans();
|
|
||||||
|
|
||||||
CoinsResult available_coins;
|
CoinsResult available_coins;
|
||||||
|
|
||||||
|
@ -765,11 +757,7 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test)
|
||||||
BOOST_AUTO_TEST_CASE(ApproximateBestSubset)
|
BOOST_AUTO_TEST_CASE(ApproximateBestSubset)
|
||||||
{
|
{
|
||||||
FastRandomContext rand{};
|
FastRandomContext rand{};
|
||||||
std::unique_ptr<CWallet> wallet = std::make_unique<CWallet>(m_node.chain.get(), "", CreateMockWalletDatabase());
|
std::unique_ptr<CWallet> wallet = NewWallet(m_node);
|
||||||
wallet->LoadWallet();
|
|
||||||
LOCK(wallet->cs_wallet);
|
|
||||||
wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
|
|
||||||
wallet->SetupDescriptorScriptPubKeyMans();
|
|
||||||
|
|
||||||
CoinsResult available_coins;
|
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
|
// 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)
|
BOOST_AUTO_TEST_CASE(SelectCoins_test)
|
||||||
{
|
{
|
||||||
std::unique_ptr<CWallet> wallet = std::make_unique<CWallet>(m_node.chain.get(), "", CreateMockWalletDatabase());
|
std::unique_ptr<CWallet> wallet = NewWallet(m_node);
|
||||||
wallet->LoadWallet();
|
LOCK(wallet->cs_wallet); // Every 'SelectCoins' call requires it
|
||||||
LOCK(wallet->cs_wallet);
|
|
||||||
wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
|
|
||||||
wallet->SetupDescriptorScriptPubKeyMans();
|
|
||||||
|
|
||||||
// Random generator stuff
|
// Random generator stuff
|
||||||
std::default_random_engine generator;
|
std::default_random_engine generator;
|
||||||
|
@ -979,12 +964,7 @@ static util::Result<SelectionResult> SelectCoinsSRD(const CAmount& target,
|
||||||
int max_weight,
|
int max_weight,
|
||||||
std::function<CoinsResult(CWallet&)> coin_setup)
|
std::function<CoinsResult(CWallet&)> coin_setup)
|
||||||
{
|
{
|
||||||
std::unique_ptr<CWallet> wallet = std::make_unique<CWallet>(m_node.chain.get(), "", CreateMockWalletDatabase());
|
std::unique_ptr<CWallet> wallet = NewWallet(m_node);
|
||||||
wallet->LoadWallet();
|
|
||||||
LOCK(wallet->cs_wallet);
|
|
||||||
wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
|
|
||||||
wallet->SetupDescriptorScriptPubKeyMans();
|
|
||||||
|
|
||||||
CoinEligibilityFilter filter(0, 0, 0); // accept all coins without ancestors
|
CoinEligibilityFilter filter(0, 0, 0); // accept all coins without ancestors
|
||||||
Groups group = GroupOutputs(*wallet, coin_setup(*wallet), cs_params, {{filter}})[filter].all_groups;
|
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);
|
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());
|
std::unique_ptr<CWallet> wallet = NewWallet(m_node);
|
||||||
wallet->LoadWallet();
|
|
||||||
LOCK(wallet->cs_wallet);
|
|
||||||
wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
|
|
||||||
wallet->SetupDescriptorScriptPubKeyMans();
|
|
||||||
|
|
||||||
auto available_coins = coin_setup(*wallet);
|
auto available_coins = coin_setup(*wallet);
|
||||||
|
|
||||||
|
LOCK(wallet->cs_wallet);
|
||||||
auto result = SelectCoins(*wallet, available_coins, /*pre_set_inputs=*/ {}, target, cc, cs_params);
|
auto result = SelectCoins(*wallet, available_coins, /*pre_set_inputs=*/ {}, target, cc, cs_params);
|
||||||
if (result) {
|
if (result) {
|
||||||
const auto signedTxSize = 10 + 34 + 68 * result->GetInputSet().size(); // static header size + output size + inputs size (P2WPKH)
|
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,
|
/*avoid_partial=*/false,
|
||||||
};
|
};
|
||||||
|
|
||||||
auto chain{m_node.chain.get()};
|
|
||||||
|
|
||||||
{
|
{
|
||||||
// Scenario 1:
|
// Scenario 1:
|
||||||
// The actor starts with 1x 50.0 BTC and 1515x 0.033 BTC (~100.0 BTC total) unspent outputs
|
// 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);
|
add_coin(available_coins, wallet, CAmount(50 * COIN), CFeeRate(0), 144, false, 0, true);
|
||||||
return available_coins;
|
return available_coins;
|
||||||
},
|
},
|
||||||
chain);
|
m_node);
|
||||||
|
|
||||||
BOOST_CHECK(result);
|
BOOST_CHECK(result);
|
||||||
// Verify that only the 50 BTC UTXO was selected
|
// Verify that only the 50 BTC UTXO was selected
|
||||||
|
@ -1157,7 +1131,7 @@ BOOST_AUTO_TEST_CASE(check_max_weight)
|
||||||
}
|
}
|
||||||
return available_coins;
|
return available_coins;
|
||||||
},
|
},
|
||||||
chain);
|
m_node);
|
||||||
|
|
||||||
BOOST_CHECK(has_coin(result->GetInputSet(), CAmount(0.0625 * COIN)));
|
BOOST_CHECK(has_coin(result->GetInputSet(), CAmount(0.0625 * COIN)));
|
||||||
BOOST_CHECK(has_coin(result->GetInputSet(), CAmount(0.025 * 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;
|
return available_coins;
|
||||||
},
|
},
|
||||||
chain);
|
m_node);
|
||||||
|
|
||||||
// No results
|
// No results
|
||||||
// 1515 inputs * 68 bytes = 103,020 bytes
|
// 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.
|
// 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.
|
// 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());
|
std::unique_ptr<CWallet> wallet = NewWallet(m_node);
|
||||||
wallet->LoadWallet();
|
|
||||||
LOCK(wallet->cs_wallet);
|
|
||||||
wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
|
|
||||||
wallet->SetupDescriptorScriptPubKeyMans();
|
|
||||||
|
|
||||||
CoinsResult available_coins;
|
CoinsResult available_coins;
|
||||||
{
|
{
|
||||||
std::unique_ptr<CWallet> dummyWallet = std::make_unique<CWallet>(m_node.chain.get(), "dummy", CreateMockWalletDatabase());
|
std::unique_ptr<CWallet> dummyWallet = NewWallet(m_node, /*wallet_name=*/"dummy");
|
||||||
dummyWallet->LoadWallet();
|
|
||||||
LOCK(dummyWallet->cs_wallet);
|
|
||||||
dummyWallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
|
|
||||||
dummyWallet->SetupDescriptorScriptPubKeyMans();
|
|
||||||
|
|
||||||
add_coin(available_coins, *dummyWallet, 100000); // 0.001 BTC
|
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.SetInputWeight(output.outpoint, 148);
|
||||||
cc.SelectExternal(output.outpoint, output.txout);
|
cc.SelectExternal(output.outpoint, output.txout);
|
||||||
|
|
||||||
|
LOCK(wallet->cs_wallet);
|
||||||
const auto preset_inputs = *Assert(FetchSelectedInputs(*wallet, cc, cs_params));
|
const auto preset_inputs = *Assert(FetchSelectedInputs(*wallet, cc, cs_params));
|
||||||
available_coins.Erase({available_coins.coins[OutputType::BECH32].begin()->outpoint});
|
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.
|
// Test case to verify CoinsResult object sanity.
|
||||||
CoinsResult available_coins;
|
CoinsResult available_coins;
|
||||||
{
|
{
|
||||||
std::unique_ptr<CWallet> dummyWallet = std::make_unique<CWallet>(m_node.chain.get(), "dummy", CreateMockWalletDatabase());
|
std::unique_ptr<CWallet> dummyWallet = NewWallet(m_node, /*wallet_name=*/"dummy");
|
||||||
BOOST_CHECK_EQUAL(dummyWallet->LoadWallet(), DBErrors::LOAD_OK);
|
|
||||||
LOCK(dummyWallet->cs_wallet);
|
|
||||||
dummyWallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
|
|
||||||
dummyWallet->SetupDescriptorScriptPubKeyMans();
|
|
||||||
|
|
||||||
// Add some coins to 'available_coins'
|
// Add some coins to 'available_coins'
|
||||||
for (int i=0; i<10; i++) {
|
for (int i=0; i<10; i++) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue