Skip to content

feat!: split NoBnbSolution into infeasible vs round-limit variants#55

Merged
evanlinjin merged 1 commit into
bitcoindevkit:masterfrom
evanlinjin:feat/bnb-infeasible-error
Jul 8, 2026
Merged

feat!: split NoBnbSolution into infeasible vs round-limit variants#55
evanlinjin merged 1 commit into
bitcoindevkit:masterfrom
evanlinjin:feat/bnb-infeasible-error

Conversation

@evanlinjin

Copy link
Copy Markdown
Member

Description

run_bnb's failure is currently a single NoBnbSolution { max_rounds, rounds }, which conflates three different situations. This makes it an enum:

  • InsufficientFunds — the candidates can't cover the target value.
  • MaxWeightExceeded — the value is coverable, but every selection busts max_weight (mirrors the SelectError from select_until_target_met).
  • RoundLimit { max_rounds, rounds } — hit the round cap; a solution may still exist with more rounds.

How — without touching BnbMetric

The metric returning None just means "prune"; it never needs an error channel. All the information already lives in run_bnb: if the search runs to completion (rounds < max_rounds, or a final pull drains the iterator) then the tree was fully explored and no selection satisfies the target — a genuine infeasibility. A cheap is_fundable value check then splits that into value (InsufficientFunds) vs weight (MaxWeightExceeded). If instead we stopped on the round cap, it's RoundLimit.

The MaxWeightExceeded attribution is sound for the crate's metrics: a cap-blind metric can only exhaust-empty when the value itself is unreachable (otherwise it would have returned an over-cap selection, not failed), so you never falsely land there.

Breaking

NoBnbSolution becomes an enum; the max_rounds/rounds fields move under the RoundLimit variant. Display/Error still hold.

Tests

Deterministic tests for each variant: run_bnb_reports_{insufficient_funds,max_weight_exceeded,round_limit}.

🤖 Generated with Claude Code

@evanlinjin
evanlinjin requested a review from LLFourn July 8, 2026 07:18
@LLFourn

LLFourn commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

conceptACK

`run_bnb` failing conflated three different cases behind one struct. Make
`NoBnbSolution` an enum that says which happened:

- `InsufficientFunds` — the candidates can't cover the target value.
- `MaxWeightExceeded` — the value is coverable, but every selection busts
  `max_weight` (mirrors `SelectError`).
- `RoundLimit { max_rounds, rounds }` — hit the round cap; a solution may
  still exist with more rounds.

The distinction is derivable in `run_bnb` without giving `BnbMetric` an error
channel: if the search runs to completion (rounds < max_rounds, or a final
pull drains the iterator) then no selection satisfies the target — a genuine
infeasibility — and a cheap `is_fundable` value check splits it into value vs
weight. Otherwise we merely ran out of rounds.

Breaking: `NoBnbSolution` is now an enum; its `max_rounds`/`rounds` fields move
under the `RoundLimit` variant.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@evanlinjin
evanlinjin force-pushed the feat/bnb-infeasible-error branch from b3366a0 to 4d5349e Compare July 8, 2026 07:57
@evanlinjin
evanlinjin merged commit 56c1a09 into bitcoindevkit:master Jul 8, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants