Summary
This release brings substantial improvements to the coin selection API, timelock handling, and transaction construction ergonomics.
Change outputs
The ChangePolicyType enum and change_descriptor field on SelectorParams have been replaced by a new ChangeScript type (#18, #39). ChangeScript can be constructed from either a DefiniteDescriptor or a raw ScriptBuf with an explicit satisfaction weight. Change policy parameters — dust relay feerate, minimum change value, and long-term feerate — are now fields directly on SelectorParams rather than a separate type. SelectorParams::new now takes change_script: ChangeScript as its third argument.
Timelock and spendability improvements
TxStatus has been renamed to ConfirmationStatus and its time field replaced by prev_mtp: Option<Time>, reflecting that median-time-past may not be known for all confirmed transactions (#36). is_timelocked now takes (tip_height: Height, tip_mtp: Option<Time>) and returns Option<bool> to account for unknown MTP. Dedicated is_block_timelocked and is_time_timelocked methods are also added. filter_unspendable_now is renamed to filter_unspendable.
Anti-fee-sniping (BIP326)
Anti-fee-sniping support is new in 0.2.0. Set PsbtParams::anti_fee_sniping to Some(tip_height) to enable it; None (the default) leaves the transaction unchanged (#5, #65). The implementation correctly preserves accumulated input CLTV requirements. A new AntiFeeSnipingError type is introduced, wrapped under CreatePsbtError::AntiFeeSniping, for cases where AFS cannot be applied (e.g. a non-height-based locktime or an unsupported transaction version).
Per-input sequence control
Input::set_sequence allows callers to override nSequence per input, validated against the input's CSV and CLTV requirements (#66). Input::from_psbt_input gains an absolute_timelock: Option<LockTime> parameter; passing a CLTV requirement when the sequence is Sequence::MAX returns an error.
Selection encapsulation
Selection::inputs and Selection::outputs are now accessor methods rather than public fields (#72). This prevents callers from replacing an input after coin selection has balanced the transaction. Mutable access goes through the new InputMut handle (returned by Selection::input_mut and Selection::inputs_mut), which only exposes set_sequence. Sort and shuffle methods (sort_inputs_by, sort_outputs_by, shuffle_inputs, shuffle_outputs) are also added.
RBF: descendant fee
RbfParams::new and RbfSet::new now require a descendant_fee: Amount parameter representing fees from transactions that would be evicted alongside the replaced transaction (#50). This ensures the replacement fee floor is computed correctly per replacement policy (Rule 3).
What's Changed
- Update
Cargo.tomlfor initial release by @evanlinjin in #6 - Fix clippy by @evanlinjin in #11
- feat(selector): allow multiple change sources with ChangeDescriptor by @nymius in #18
- feat: update signer impl for XOnlyPubkey by @chaitika in #20
- chore: bump MSRV to 1.85.0 by @aagbotemi in #23
- ci: pin
hometo 0.5.11 by @ValuedMammal in #27 - Include
fallback_locktimein locktime accumulation by @ValuedMammal in #24 - feat(selection)!: Add member
PsbtParams::sighash_typeby @ValuedMammal in #25 - selector!: Swap
ChangePolicyTypeforbdk_coin_select::ChangePolicyby @ValuedMammal in #32 - feat(selector): implement absolute fee targeting strategy by @aagbotemi in #31
- docs: Improve documentation of
Finalizerby @ValuedMammal in #34 - feat: enable random anti-fee sniping by @aagbotemi in #5
- Pin
timeandtime-corefor MSRV by @evanlinjin in #37 - Fix locktime calculations and improve API by @evanlinjin in #36
- refactor!: Remove FeeStrategy add ChangeScript and improve SelectorParams by @evanlinjin in #39
- fix(selection): Improve handling of fallback locktime by @ValuedMammal in #43
- fix(finalizer): set finalized to false on error and add full coverage by @noahjoeris in #44
- ci: update CI actions and enable caching by @noahjoeris in #46
- ci: add code coverage workflow by @noahjoeris in #45
- fix(deps): replace deprecated FeeRate::from_sat_per_vb_unchecked by @noahjoeris in #51
- refactor(input-candidates): clarify caches and drop unused errors by @noahjoeris in #53
- chore: add GitHub issue and PR templates by @noahjoeris in #55
- feat(input): add set_sequence for per-input sequence override by @aagbotemi in #66
- fix(rbf)!: include evicted descendants in replacement fee floor by @noahjoeris in #50
- fix(afs)!: preserve input timelock requirements by @aagbotemi in #65
- refactor(selection)!: encapsulate Selection and fail-fast on mixed-unit locktimes by @evanlinjin in #72
- Release
0.2.0by @ValuedMammal in #35
New Contributors
- @nymius made their first contribution in #18
- @chaitika made their first contribution in #20
- @aagbotemi made their first contribution in #23
- @ValuedMammal made their first contribution in #27
- @noahjoeris made their first contribution in #44
Full Changelog: 0.1.0...0.2.0