@@ -146,6 +146,42 @@ BOOST_AUTO_TEST_CASE(bnb_test)
146
146
AddCoins (clone_pool, {2 * CENT, 7 * CENT, 7 * CENT});
147
147
AddDuplicateCoins (clone_pool, 50'000 , 5 * CENT);
148
148
TestBnBSuccess (" Skip equivalent input sets" , clone_pool, /* selection_target=*/ 16 * CENT, /* expected_input_amounts=*/ {2 * CENT, 7 * CENT, 7 * CENT});
149
+
150
+ /* Test BnB attempt limit (`TOTAL_TRIES`)
151
+ *
152
+ * Generally, on a diverse UTXO pool BnB will quickly pass over UTXOs bigger than the target and then start
153
+ * combining small counts of UTXOs that in sum remain under the selection_target+cost_of_change. When there are
154
+ * multiple UTXOs that have matching amount and cost, combinations with equivalent input sets are skipped. The UTXO
155
+ * pool for this test is specifically crafted to create as much branching as possible. The selection target is
156
+ * 8 CENT while all UTXOs are slightly bigger than 1 CENT. The smallest eight are 100,000…100,007 sats, while the larger
157
+ * nine are 100,368…100,375 (i.e., 100,008…100,016 sats plus cost_of_change (359 sats)).
158
+ *
159
+ * Because BnB will only select input sets that fall between selection_target and selection_target + cost_of_change,
160
+ * and the search traverses the UTXO pool from large to small amounts, the search will visit every single
161
+ * combination of eight inputs. All except the last combination will overshoot by more than cost_of_change on the
162
+ * eighth input, because the larger nine inputs each exceed 1 CENT by more than cost_of_change. Only the last
163
+ * combination consisting of the eight smallest UTXOs falls into the target window.
164
+ */
165
+ std::vector<OutputGroup> doppelganger_pool;
166
+ std::vector<CAmount> doppelgangers;
167
+ std::vector<CAmount> expected_inputs;
168
+ for (int i = 0 ; i < 17 ; ++i) {
169
+ if (i < 8 ) {
170
+ // The eight smallest UTXOs can be combined to create expected_result
171
+ doppelgangers.push_back (1 * CENT + i);
172
+ expected_inputs.push_back (doppelgangers[i]);
173
+ } else {
174
+ // Any eight UTXOs including at least one UTXO with the added cost_of_change will exceed target window
175
+ doppelgangers.push_back (1 * CENT + default_cs_params.m_cost_of_change + i);
176
+ }
177
+ }
178
+ AddCoins (doppelganger_pool, doppelgangers);
179
+ // Among up to 17 unique UTXOs of similar effective value we will find a solution composed of the eight smallest UTXOs
180
+ TestBnBSuccess (" Combine smallest 8 of 17 unique UTXOs" , doppelganger_pool, /* selection_target=*/ 8 * CENT, /* expected_input_amounts=*/ expected_inputs);
181
+
182
+ // Starting with 18 unique UTXOs of similar effective value we will not find the solution due to exceeding the attempt limit
183
+ AddCoins (doppelganger_pool, {1 * CENT + default_cs_params.m_cost_of_change + 17 });
184
+ TestBnBFail (" Exhaust looking for smallest 8 of 18 unique UTXOs" , doppelganger_pool, /* selection_target=*/ 8 * CENT);
149
185
}
150
186
151
187
BOOST_AUTO_TEST_CASE (bnb_feerate_sensitivity_test)
0 commit comments