knapsack_solver_test exceeds 21M BTC #35449

issue hodlinator opened this issue on June 3, 2026
  1. hodlinator commented at 2:05 PM on June 3, 2026: contributor

    In resuming my experimentation around making CAmount a safer type, but ran into the unit test case knapsack_solver_test in coinselector_tests.cpp exceeding 21M BTC. This can be observed on master as of 654a5223af532e965998bb1d6988be421fba186f by applying:

    --- a/src/wallet/test/coinselector_tests.cpp
    +++ b/src/wallet/test/coinselector_tests.cpp
    @@ -505,6 +505,7 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test)
             available_coins.Clear();
             for (int j = 0; j < 20; j++)
                 add_coin(available_coins, *wallet, 50000 * COIN);
    +        assert(available_coins.GetTotalAmount() <= MAX_MONEY);
     
             const auto result19 = KnapsackSolver(KnapsackGroupOutputs(available_coins, *wallet, filter_confirmed), 500000 * COIN, CENT);
             BOOST_CHECK(result19);
    

    There is an outer loop with 100 iterations, so 100x20x50'000 BTC = 100'000'000 BTC.

    I'm sure there is an easy fix. Just don't want to be resetting too much state to make the tests not cover some case they should be, so hoping this issue will help uncover a good solution.

  2. fanquake commented at 2:05 PM on June 3, 2026: member
  3. furszy commented at 2:23 PM on June 3, 2026: member

    CENT instead of COIN and done?

  4. hodlinator commented at 3:02 PM on June 3, 2026: contributor

    CENT instead of COIN and done?

    I think COIN is pretty essential to the case we are testing for, given the comment:

    https://github.com/bitcoin/bitcoin/blob/654a5223af532e965998bb1d6988be421fba186f/src/wallet/test/coinselector_tests.cpp#L503-L507

  5. furszy commented at 3:21 PM on June 3, 2026: member

    hehe, I only read the lines you shared in the description. Just went deeper.. the issue isn't the test case; it clears the available coins right before start, so available coins shouldn't be compounding across loop iterations. The problem is inside CoinsResult::Clear:

    void CoinsResult::Clear() {
        coins.clear();
    }
    

    We are missing to clear the other two cached fields total_amount and total_effective_amount. That should fix the issue.

    void CoinsResult::Clear() {
         coins.clear();
    +    total_amount = 0;
    +    total_effective_amount = std::nullopt;
     }
    
  6. hodlinator commented at 8:22 PM on June 3, 2026: contributor

    Thanks @furszy, I'm cooking up a PR with a commit in the direction you suggested! Should be ready for review together with some other minor changes by tomorrow.

  7. murchandamus commented at 8:50 PM on June 3, 2026: member

    The correct solution is of course to remove the Knapsack coinselection algorithm. ;)

    Jokes aside, thanks for surfacing why the amount compounded across loops, @furszy, I was about to check why it did when I saw your comment.

  8. hodlinator commented at 7:35 AM on June 4, 2026: contributor
  9. sedited closed this on Jun 8, 2026

  10. sedited referenced this in commit e36f5d5d0b on Jun 8, 2026
  11. sedited referenced this in commit b5e91e946c on Jun 8, 2026

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-06-11 10:51 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me