Describe the bug
DrainWeights::dust_threshold computes the threshold from the drain's actual output_weight + spend_weight. For DrainWeights::TR_KEYSPEND that is 172 + 230 = 402 WU, which at the default 3 sat/vB dust relay feerate gives 302 sats. Bitcoin Core's dust rule for segwit outputs instead assumes a fixed 67 vB spend size, which is why a P2TR output is dust below 330 sats (matching the crate's own TR_DUST_RELAY_MIN_VALUE).
Since LowestFee::drain_value relies on dust_threshold, it can return a P2TR change output valued between 302 and 329 sats, which default Bitcoin Core relay policy treats as dust.
This issue was found by AI.
To Reproduce
use bdk_coin_select::{
metrics::LowestFee, BnbMetric, Candidate, CoinSelector, DrainWeights, FeeRate, Target,
TargetFee, TargetOutputs, TR_DUST_RELAY_MIN_VALUE,
};
#[test]
fn does_not_create_p2tr_change_below_core_dust_threshold() {
let candidates = [Candidate {
value: 1_000,
weight: 1,
input_count: 1,
is_segwit: true,
}];
let mut cs = CoinSelector::new(&candidates);
assert!(cs.select(0));
let target = Target {
fee: TargetFee::ZERO,
outputs: TargetOutputs {
value_sum: 1_000 - (TR_DUST_RELAY_MIN_VALUE - 10),
weight_sum: 1,
n_outputs: 1,
},
max_weight: None,
};
let mut metric = LowestFee {
long_term_feerate: FeeRate::from_sat_per_vb(1.0),
dust_relay_feerate: FeeRate::from_sat_per_vb(3.0),
drain_weights: DrainWeights::TR_KEYSPEND,
};
// Fails: returns a drain with value 320.
assert!(metric.drain(&cs, target).is_none());
}
Expected behavior
The dust threshold used by LowestFee should not produce change outputs that Bitcoin Core's default dust relay policy rejects (i.e. below 330 sats for P2TR at 3 sat/vB).
Describe the bug
DrainWeights::dust_thresholdcomputes the threshold from the drain's actualoutput_weight + spend_weight. ForDrainWeights::TR_KEYSPENDthat is 172 + 230 = 402 WU, which at the default 3 sat/vB dust relay feerate gives 302 sats. Bitcoin Core's dust rule for segwit outputs instead assumes a fixed 67 vB spend size, which is why a P2TR output is dust below 330 sats (matching the crate's ownTR_DUST_RELAY_MIN_VALUE).Since
LowestFee::drain_valuerelies ondust_threshold, it can return a P2TR change output valued between 302 and 329 sats, which default Bitcoin Core relay policy treats as dust.This issue was found by AI.
To Reproduce
Expected behavior
The dust threshold used by
LowestFeeshould not produce change outputs that Bitcoin Core's default dust relay policy rejects (i.e. below 330 sats for P2TR at 3 sat/vB).