Skip to content

fix(coin_selection): calculate_cs_result returns the required UTXOs first#390

Open
ValuedMammal wants to merge 3 commits intobitcoindevkit:masterfrom
ValuedMammal:fix/calculate_cs_result
Open

fix(coin_selection): calculate_cs_result returns the required UTXOs first#390
ValuedMammal wants to merge 3 commits intobitcoindevkit:masterfrom
ValuedMammal:fix/calculate_cs_result

Conversation

@ValuedMammal
Copy link
Collaborator

@ValuedMammal ValuedMammal commented Mar 2, 2026

Description

Follow-up to #262 that addresses transaction input ordering when BnB finds a solution.

Previously calculate_cs_result produced a CoinSelectionResult by appending the required UTXOs onto the selected ones, which changed the expected order of transaction inputs.

calculate_cs_result now returns the required UTXOs before the newly selected ones. This behavior aligns with the expectation that the order of manually selected inputs should be preserved in the final transaction whenever TxOrdering::Untouched is specified.

For related discussion refer to #244 (comment).

Changelog notice

Fixed

  • wallet: Fixed order of selected UTXOs for BranchAndBoundCoinSelection, required UTXOs come first

Checklists

All Submissions:

Bugfixes:

  • I've added tests to reproduce the issue which are now passing
  • I'm linking the issue being fixed by this PR

… first

Previously `calculate_cs_result` produced a CoinSelectionResult by
appending the required utxos onto the selected ones, which changed
the order of transaction inputs when TxOrdering::Untouched was
specified. The intended behavior is for the order of the inputs
to match the order in which the utxos were added to the TxBuilder.
We fix this by extending the required_utxos Vec with the
selected_utxos before returning the CoinSelectionResult.
…ering_bnb_success`

The test is set up in such a way that BnB can find a solution
and demonstrates that `calculate_cs_result` correctly places
required UTXOs before selected ones.
@ValuedMammal ValuedMammal self-assigned this Mar 2, 2026
@ValuedMammal ValuedMammal moved this to Needs Review in BDK Wallet Mar 2, 2026
@ValuedMammal ValuedMammal added the bug Something isn't working label Mar 2, 2026
@codecov
Copy link

codecov bot commented Mar 2, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 79.77%. Comparing base (c422104) to head (96c62d5).
⚠️ Report is 12 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #390      +/-   ##
==========================================
+ Coverage   79.17%   79.77%   +0.60%     
==========================================
  Files          24       24              
  Lines        5311     5267      -44     
  Branches      242      241       -1     
==========================================
- Hits         4205     4202       -3     
+ Misses       1029      988      -41     
  Partials       77       77              
Flag Coverage Δ
rust 79.77% <100.00%> (+0.60%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Serious-Sam-Dev
Copy link

all test and clippy passed, i dont see any problem, ACK

Copy link
Contributor

@110CodingP 110CodingP left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 378cb24

Though unrelated to the PR I was wondering whether we should also have a test to check the following invariant in add_utxos ?
"If a UTXO is inserted multiple times, only the final insertion will take effect."

@ValuedMammal
Copy link
Collaborator Author

Thank you @110CodingP

"If a UTXO is inserted multiple times, only the final insertion will take effect."

We do have these tests, or are you referring to something else?

@110CodingP
Copy link
Contributor

Sorry for being brief, I meant something like this:

// This demonstrates that `add_utxo` only considers the final insertion.
#[test]
fn test_add_utxos_final_op_retained() {
    // Create empty wallet
    let (desc, change_desc) = get_test_wpkh_and_change_desc();
    let mut wallet = Wallet::create(desc, change_desc)
        .network(bdk_wallet::bitcoin::Network::Regtest)
        .create_wallet_no_persist()
        .unwrap();

    let outpoint_0 = receive_output(
        &mut wallet,
        Amount::from_sat(35_000),
        ReceiveTo::Mempool(50),
    );
    let outpoint_1 = receive_output(
        &mut wallet,
        Amount::from_sat(25_200),
        ReceiveTo::Mempool(100),
    );

    let send_to = wallet.next_unused_address(KeychainKind::External).address;
    let mut tx_builder = wallet.build_tx();
    tx_builder
        .add_utxo(outpoint_0)
        .unwrap()
        .add_utxo(outpoint_1)
        .unwrap()
        .add_utxo(outpoint_0)
        .unwrap()
        .add_recipient(send_to.script_pubkey(), Amount::from_sat(60_000))
        .fee_rate(FeeRate::from_sat_per_vb(1).unwrap())
        .ordering(bdk_wallet::TxOrdering::Untouched);
    let psbt = tx_builder.finish().unwrap();

    // Fails
    assert_eq!(
        psbt.unsigned_tx
            .input
            .iter()
            .map(|txin| txin.previous_output)
            .collect::<Vec<_>>(),
        vec![outpoint_0, outpoint_1]
    );
}

Check that for repeated calls to `add_utxo`, given the same outpoint,
the final insertion takes effect.

Consolidate `use` statements in `tx_builder::test` mod.

Co-authored-by: codingp110 <codingp110@gmail.com>
@ValuedMammal ValuedMammal mentioned this pull request Mar 9, 2026
2 tasks
@ValuedMammal ValuedMammal added this to the Wallet 3.1.0 milestone Mar 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

Status: Needs Review

Development

Successfully merging this pull request may close these issues.

3 participants