Skip to content

fix(wallet): manual coin selection and RBF toggle - #2473

Merged
ethicnology merged 2 commits into
developfrom
fix/bdk-txbuilder-immutable-selection
Aug 18, 2026
Merged

fix(wallet): manual coin selection and RBF toggle#2473
ethicnology merged 2 commits into
developfrom
fix/bdk-txbuilder-immutable-selection

Conversation

@ethicnology

Copy link
Copy Markdown
Member

bdk_dart's TxBuilder is immutable — every method returns a new builder instance instead of mutating in place. Two call sites in buildPsbt discarded the return value, silently no-opping both manual UTXO selection and the RBF-off toggle: BDK always picked inputs on its own regardless of the user's coin selection, and disabling RBF never actually changed the sequence field.

Pre-existing on main.

Affects hot wallets and every remote signer (Ledger/BitBox/Trezor) identically.

Adds an offline regression test that funds a real BDK wallet via a hand-crafted unconfirmed transaction (no network) and exercises buildPsbt end-to-end, proving manual selection now overrides otherwise-unspendable coins and that the RBF sequence is set correctly in both directions.

bdk_dart's TxBuilder is immutable — every method returns a new builder
instance instead of mutating in place. Two call sites in buildPsbt
discarded the return value, silently no-opping both manual UTXO
selection and the RBF-off toggle: BDK always picked inputs on its own
regardless of the user's coin selection, and disabling RBF never
actually changed the sequence field.

Pre-existing on main (not trezor-specific); affects hot wallets and
every remote signer (Ledger/BitBox/Trezor) identically.

Adds an offline regression test that funds a real BDK wallet via a
hand-crafted unconfirmed transaction (no network) and exercises
buildPsbt end-to-end, proving manual selection now overrides
otherwise-unspendable coins and that the RBF sequence is set
correctly in both directions.
@ethicnology ethicnology self-assigned this Jul 18, 2026
@claude

This comment was marked as resolved.

Two hardenings surfaced by review of the TxBuilder reassignment fix:

1. D7 defense in depth: BDK's documented semantics let a manually
   added utxo (TxBuilder.addUtxos) override the unspendable filter —
   the inverse of the app-level D7 invariant that a frozen coin must
   never be spendable. Production was protected only by
   PrepareBitcoinSendUsecase stripping frozen coins from the
   selection; any caller bypassing that usecase (or working from a
   stale utxo fetch) would not be. BitcoinWalletRepository now takes
   FrozenWalletUtxoDatasource and reads the frozen table LIVE at build
   time: frozen outpoints are merged into the unspendable list handed
   to BDK (automatic selection can never pick a frozen coin, whatever
   the caller passed) and stripped from the manual selection (a frozen
   coin can't be forced in via the addUtxos override either).
   Payjoin-derived exclusions stay at the usecase — they come from
   another repository, which this repository must not depend on. The
   datasource keeps raw BDK semantics (thin wrapper); its regression
   test comment documents that inversion explicitly.

2. replaceByFee null default flipped from false to true: harmless
   while the datasource's setExactSequence call discarded its result,
   but wrong once fixed — a caller omitting the flag would have
   started disabling RBF by default, diverging from the datasource
   default and BDK's default sequence (0xFFFFFFFD).

Repository unit tests (mocktail, frozen store mocked) cover: live-read
strip when the caller passes no unspendable list, frozen ∪ caller
merge (deduped), caller-list stripping by exact outpoint (txId alone
not enough), and RBF flag defaulting/forwarding.
@ethicnology
ethicnology force-pushed the fix/bdk-txbuilder-immutable-selection branch from f7e5114 to 04eeb3e Compare July 18, 2026 14:18
@ethicnology
ethicnology requested a review from i5hi July 18, 2026 14:53
@ethicnology
ethicnology merged commit f3d064b into develop Aug 18, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant