@@ -15,20 +15,23 @@ BOOST_FIXTURE_TEST_SUITE(coinselection_tests, TestingSetup)
15
15
static int next_lock_time = 0 ;
16
16
static FastRandomContext default_rand;
17
17
18
+ static const int P2WPKH_INPUT_VSIZE = 68 ;
19
+ static const int P2WPKH_OUTPUT_VSIZE = 31 ;
20
+
18
21
/* * Default coin selection parameters (dcsp) allow us to only explicitly set
19
22
* parameters when a diverging value is relevant in the context of a test.
20
23
* We use P2WPKH input and output weights for the change weights. */
21
24
static CoinSelectionParams init_default_params ()
22
25
{
23
26
CoinSelectionParams dcsp{
24
27
/* rng_fast*/ default_rand,
25
- /* change_output_size=*/ 31 ,
26
- /* change_spend_size=*/ 68 ,
28
+ /* change_output_size=*/ P2WPKH_OUTPUT_VSIZE ,
29
+ /* change_spend_size=*/ P2WPKH_INPUT_VSIZE ,
27
30
/* min_change_target=*/ 50'000 ,
28
31
/* effective_feerate=*/ CFeeRate (5000 ),
29
32
/* long_term_feerate=*/ CFeeRate (10'000 ),
30
33
/* discard_feerate=*/ CFeeRate (3000 ),
31
- /* tx_noinputs_size=*/ 11 + 31 , // static header size + output size
34
+ /* tx_noinputs_size=*/ 11 + P2WPKH_OUTPUT_VSIZE , // static header size + output size
32
35
/* avoid_partial=*/ false ,
33
36
};
34
37
dcsp.m_change_fee = /* 155 sats=*/ dcsp.m_effective_feerate .GetFee (dcsp.change_output_size );
@@ -41,7 +44,7 @@ static CoinSelectionParams init_default_params()
41
44
static const CoinSelectionParams default_cs_params = init_default_params();
42
45
43
46
/* * Make one OutputGroup with a single UTXO that either has a given effective value (default) or a given amount (`is_eff_value = false`). */
44
- static OutputGroup MakeCoin (const CAmount& amount, bool is_eff_value = true , CoinSelectionParams cs_params = default_cs_params, int custom_spending_vsize = 68 )
47
+ static OutputGroup MakeCoin (const CAmount& amount, bool is_eff_value = true , CoinSelectionParams cs_params = default_cs_params, int custom_spending_vsize = P2WPKH_INPUT_VSIZE )
45
48
{
46
49
// Always assume that we only have one input
47
50
CMutableTransaction tx;
@@ -93,7 +96,7 @@ static std::string InputAmountsToString(const SelectionResult& selection)
93
96
return " [" + util::Join (selection.GetInputSet (), " " , [](const auto & input){ return util::ToString (input->txout .nValue );}) + " ]" ;
94
97
}
95
98
96
- static void TestBnBSuccess (std::string test_title, std::vector<OutputGroup>& utxo_pool, const CAmount& selection_target, const std::vector<CAmount>& expected_input_amounts, const CoinSelectionParams& cs_params = default_cs_params, int custom_spending_vsize = 68 )
99
+ static void TestBnBSuccess (std::string test_title, std::vector<OutputGroup>& utxo_pool, const CAmount& selection_target, const std::vector<CAmount>& expected_input_amounts, const CoinSelectionParams& cs_params = default_cs_params, const int custom_spending_vsize = P2WPKH_INPUT_VSIZE, const int max_selection_weight = MAX_STANDARD_TX_WEIGHT )
97
100
{
98
101
SelectionResult expected_result (CAmount (0 ), SelectionAlgorithm::BNB);
99
102
CAmount expected_amount = 0 ;
@@ -103,15 +106,18 @@ static void TestBnBSuccess(std::string test_title, std::vector<OutputGroup>& utx
103
106
expected_result.AddInput (group);
104
107
}
105
108
106
- const auto result = SelectCoinsBnB (utxo_pool, selection_target, /* cost_of_change=*/ default_cs_params.m_cost_of_change , /* max_selection_weight= */ MAX_STANDARD_TX_WEIGHT );
109
+ const auto result = SelectCoinsBnB (utxo_pool, selection_target, /* cost_of_change=*/ default_cs_params.m_cost_of_change , max_selection_weight);
107
110
BOOST_CHECK_MESSAGE (result, " Falsy result in BnB-Success: " + test_title);
108
111
BOOST_CHECK_MESSAGE (HaveEquivalentValues (expected_result, *result), strprintf (" Result mismatch in BnB-Success: %s. Expected %s, but got %s" , test_title, InputAmountsToString (expected_result), InputAmountsToString (*result)));
109
112
BOOST_CHECK_MESSAGE (result->GetSelectedValue () == expected_amount, strprintf (" Selected amount mismatch in BnB-Success: %s. Expected %d, but got %d" , test_title, expected_amount, result->GetSelectedValue ()));
110
113
}
111
114
112
- static void TestBnBFail (std::string test_title, std::vector<OutputGroup>& utxo_pool, const CAmount& selection_target)
115
+ static void TestBnBFail (std::string test_title, std::vector<OutputGroup>& utxo_pool, const CAmount& selection_target, int max_selection_weight = MAX_STANDARD_TX_WEIGHT, const bool expect_max_weight_exceeded = false )
113
116
{
114
- BOOST_CHECK_MESSAGE (!SelectCoinsBnB (utxo_pool, selection_target, /* cost_of_change=*/ default_cs_params.m_cost_of_change , /* max_selection_weight=*/ MAX_STANDARD_TX_WEIGHT), " BnB-Fail: " + test_title);
117
+ const auto result = SelectCoinsBnB (utxo_pool, selection_target, /* cost_of_change=*/ default_cs_params.m_cost_of_change , max_selection_weight);
118
+ BOOST_CHECK_MESSAGE (!result, " BnB-Fail: " + test_title);
119
+ bool max_weight_exceeded = util::ErrorString (result).original .find (" The inputs size exceeds the maximum weight" ) != std::string::npos;
120
+ BOOST_CHECK (expect_max_weight_exceeded == max_weight_exceeded);
115
121
}
116
122
117
123
BOOST_AUTO_TEST_CASE (bnb_test)
@@ -142,6 +148,10 @@ BOOST_AUTO_TEST_CASE(bnb_test)
142
148
// BnB fails to find changeless solution when overshooting by cost_of_change + 1 sat
143
149
TestBnBFail (" Overshoot upper bound" , utxo_pool, /* selection_target=*/ 4 * CENT - default_cs_params.m_cost_of_change - 1 );
144
150
151
+ TestBnBSuccess (" Select max weight" , utxo_pool, /* selection_target=*/ 4 * CENT, /* expected_input_amounts=*/ {1 * CENT, 3 * CENT}, cs_params, /* custom_spending_vsize=*/ P2WPKH_INPUT_VSIZE, /* max_selection_weight=*/ 4 * 2 * P2WPKH_INPUT_VSIZE);
152
+
153
+ TestBnBFail (" Exceed max weight" , utxo_pool, /* selection_target=*/ 4 * CENT, /* max_selection_weight=*/ 4 * 2 * P2WPKH_INPUT_VSIZE - 1 , /* expect_max_weight_exceeded=*/ true );
154
+
145
155
// Simple cases without BnB solution
146
156
TestBnBFail (" Smallest combination too big" , utxo_pool, /* selection_target=*/ 0.5 * CENT);
147
157
TestBnBFail (" No UTXO combination in target window" , utxo_pool, /* selection_target=*/ 7 * CENT);
0 commit comments