Skip to content

Commit

Permalink
Apply previous UTXO shortcut optimization
Browse files Browse the repository at this point in the history
If the index_selection is not empty, and if the previous UTXO was
excluded, then check the effective_value of the current UTXO.  If it has
the same effective_value then skip searching this branch.
  • Loading branch information
yancyribbens committed Oct 29, 2024
1 parent 193d9cc commit 4e899fc
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 8 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ A basic performance comparison between this Rust BnB implementation and [Bitcoin

|implementation|pool size|ns/iter|
|-------------:|---------|-------|
| Rust BnB| 1,000|897,810|
| Rust BnB| 1,000|598,370 |
| C++ Core BnB| 1,000|816,374|

Note: The measurements where recorded using rustc 1.75. Expect worse performance with MSRV.
Expand Down
39 changes: 32 additions & 7 deletions src/branch_and_bound.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,18 +274,23 @@ pub fn select_coins_bnb<Utxo: WeightedUtxo>(
// * Add next node to the inclusion branch.
else {
let (eff_value, utxo_waste, _) = w_utxos[index];
current_waste = current_waste.checked_add(utxo_waste)?;

index_selection.push(index);

// unchecked add is used here for performance. Since the sum of all utxo values
// did not overflow, then any positive subset of the sum will not overflow.
value = value.unchecked_add(eff_value);

// unchecked sub is used her for performance.
// The bounds for available_value are at most the sum of utxos
// and at least zero.
available_value = available_value.unchecked_sub(eff_value);

if index_selection.is_empty()
|| index - 1 == *index_selection.last().unwrap()
|| w_utxos[index].0 != w_utxos[index - 1].0
{
index_selection.push(index);
current_waste = current_waste.checked_add(utxo_waste)?;

// unchecked add is used here for performance. Since the sum of all utxo values
// did not overflow, then any positive subset of the sum will not overflow.
value = value.unchecked_add(eff_value);
}
}

// no overflow is possible since the iteration count is bounded.
Expand Down Expand Up @@ -618,6 +623,26 @@ mod tests {
assert_coin_select_params(&params, Some(&["10 cBTC", "6 cBTC", "2 cBTC"]));
}

#[test]
fn select_coins_bnb_early_bail_optimization() {
let mut utxos = vec!["7 cBTC", "7 cBTC", "7 cBTC", "7 cBTC", "2 cBTC"];
for _i in 0..50_000 {
utxos.push("5 cBTC");
}
let params = ParamsStr {
target: "30 cBTC",
cost_of_change: "5000 sats",
fee_rate: "0",
lt_fee_rate: "0",
weighted_utxos: utxos,
};

assert_coin_select_params(
&params,
Some(&["7 cBTC", "7 cBTC", "7 cBTC", "7 cBTC", "2 cBTC"]),
);
}

#[test]
fn select_coins_bnb_exhaust() {
// Recreate make_hard from bitcoin core test suit.
Expand Down

0 comments on commit 4e899fc

Please sign in to comment.