@@ -15,20 +15,23 @@ BOOST_FIXTURE_TEST_SUITE(coinselection_tests, TestingSetup)
1515static int next_lock_time = 0 ;
1616static FastRandomContext default_rand;
1717
18+ static const int P2WPKH_INPUT_VSIZE = 68 ;
19+ static const int P2WPKH_OUTPUT_VSIZE = 31 ;
20+
1821/* * Default coin selection parameters (dcsp) allow us to only explicitly set
1922 * parameters when a diverging value is relevant in the context of a test.
2023 * We use P2WPKH input and output weights for the change weights. */
2124static CoinSelectionParams init_default_params ()
2225{
2326 CoinSelectionParams dcsp{
2427 /* 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 ,
2730 /* min_change_target=*/ 50'000 ,
2831 /* effective_feerate=*/ CFeeRate (5000 ),
2932 /* long_term_feerate=*/ CFeeRate (10'000 ),
3033 /* 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
3235 /* avoid_partial=*/ false ,
3336 };
3437 dcsp.m_change_fee = /* 155 sats=*/ dcsp.m_effective_feerate .GetFee (dcsp.change_output_size );
@@ -41,7 +44,7 @@ static CoinSelectionParams init_default_params()
4144static const CoinSelectionParams default_cs_params = init_default_params();
4245
4346/* * 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 )
4548{
4649 // Always assume that we only have one input
4750 CMutableTransaction tx;
@@ -93,7 +96,7 @@ static std::string InputAmountsToString(const SelectionResult& selection)
9396 return " [" + util::Join (selection.GetInputSet (), " " , [](const auto & input){ return util::ToString (input->txout .nValue );}) + " ]" ;
9497}
9598
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 )
97100{
98101 SelectionResult expected_result (CAmount (0 ), SelectionAlgorithm::BNB);
99102 CAmount expected_amount = 0 ;
@@ -103,15 +106,15 @@ static void TestBnBSuccess(std::string test_title, std::vector<OutputGroup>& utx
103106 expected_result.AddInput (group);
104107 }
105108
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);
107110 BOOST_CHECK_MESSAGE (result, " Falsy result in BnB-Success: " + test_title);
108111 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)));
109112 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 ()));
110113}
111114
112- static void TestBnBFail (std::string test_title, std::vector<OutputGroup>& utxo_pool, const CAmount& selection_target, const bool expect_max_weight_exceeded = false )
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 )
113116{
114- 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 );
117+ const auto result = SelectCoinsBnB (utxo_pool, selection_target, /* cost_of_change=*/ default_cs_params.m_cost_of_change , max_selection_weight);
115118 BOOST_CHECK_MESSAGE (!result, " BnB-Fail: " + test_title);
116119 bool max_weight_exceeded = util::ErrorString (result).original .find (" The inputs size exceeds the maximum weight" ) != std::string::npos;
117120 BOOST_CHECK (expect_max_weight_exceeded == max_weight_exceeded);
@@ -145,6 +148,10 @@ BOOST_AUTO_TEST_CASE(bnb_test)
145148 // BnB fails to find changeless solution when overshooting by cost_of_change + 1 sat
146149 TestBnBFail (" Overshoot upper bound" , utxo_pool, /* selection_target=*/ 4 * CENT - default_cs_params.m_cost_of_change - 1 );
147150
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+
148155 // Simple cases without BnB solution
149156 TestBnBFail (" Smallest combination too big" , utxo_pool, /* selection_target=*/ 0.5 * CENT);
150157 TestBnBFail (" No UTXO combination in target window" , utxo_pool, /* selection_target=*/ 7 * CENT);
0 commit comments