Merge bitcoin/bitcoin#33701: test: add case where TOTAL_TRIES is exceeded yet solution remains

b189a345574460f10165862eca9cc40ff3337dca test: add case where `TOTAL_TRIES` is exceeded yet solution remains (yancy)

Pull request description:

  Show that `CoinGrider` halts searching when the number of attempts exceeds `TOTAL_TRIES`.  To do so, show that a solution is found, then add one more entry to the same set of inputs.  Since the search orders by `effective_value`, the solution is constructed such that only values with the lowest `effective_value` have the least weight.  Only the lowest weight values will not exceed the `max_selection_weight`. Therefore, `CoinGrinder` will not evaluate all lowest weight solutions together before exceeding `TOTAL_TRIES` since they are last found.

  This test case was inspired by a similar test for `BnB` currently named `bnb_test`.

ACKs for top commit:
  frankomosh:
    Code review ACK b189a34
  achow101:
    ACK b189a345574460f10165862eca9cc40ff3337dca
  murchandamus:
    ACK b189a345574460f10165862eca9cc40ff3337dca

Tree-SHA512: 1df0b6e29ae219edbeed14cfa97f0ad4688d6bf97ed946719ba3c3b69e004f3dee82991578eb5aceb554914b70c5b68feff9e321283c1fc8bc0fedf08df2cb4c
This commit is contained in:
Ava Chow 2026-01-30 18:26:07 -08:00
commit 705705e5b1
No known key found for this signature in database
GPG Key ID: 17565732E08E5E41

View File

@ -1149,6 +1149,41 @@ BOOST_AUTO_TEST_CASE(coin_grinder_tests)
size_t expected_attempts = 7;
BOOST_CHECK_MESSAGE(res->GetSelectionsEvaluated() == expected_attempts, strprintf("Expected %i attempts, but got %i", expected_attempts, res->GetSelectionsEvaluated()));
}
{
// #################################################################################################################
// 8) Test input set that has a solution will not find a solution before reaching the attempt limit
// #################################################################################################################
CAmount target = 8 * COIN;
int max_selection_weight = 3200; // WU
dummy_params.m_min_change_target = 0;
const auto& result_a = CoinGrinder(target, dummy_params, m_node, max_selection_weight, [&](CWallet& wallet) {
CoinsResult doppelgangers;
for (int i = 0; i < 18; ++i) {
add_coin(doppelgangers, wallet, CAmount(1 * COIN + i), CFeeRate(0), 144, false, 0, true, 96 + i);
}
return doppelgangers;
});
BOOST_CHECK(result_a);
SelectionResult expected_result(CAmount(0), SelectionAlgorithm::CG);
for (int i = 0; i < 8; ++i) {
add_coin(1 * COIN + i, 0, expected_result);
}
BOOST_CHECK(EquivalentResult(expected_result, *result_a));
// Demonstrate a solution is found before the attempts limit is reached.
size_t expected_attempts = 87'525;
BOOST_CHECK_MESSAGE(result_a->GetSelectionsEvaluated() == expected_attempts, strprintf("Expected %i attempts, but got %i", expected_attempts, result_a->GetSelectionsEvaluated()));
// Adding one more doppelganger causes the attempt limit to be reached before finding a solution.
const auto& result_b = CoinGrinder(target, dummy_params, m_node, max_selection_weight, [&](CWallet& wallet) {
CoinsResult doppelgangers;
for (int i = 0; i < 19; ++i) {
add_coin(doppelgangers, wallet, CAmount(1 * COIN + i), CFeeRate(0), 144, false, 0, true, 96 + i);
}
return doppelgangers;
});
BOOST_CHECK(!result_b);
}
}
static util::Result<SelectionResult> SelectCoinsSRD(const CAmount& target,