Skip to content

DrainWeights::dust_threshold is below Bitcoin Core's dust limit for P2TR change #81

Description

@noahjoeris

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).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions