Skip to content

[v0.1.x-branch] Backport #1066: txconfirm: release abandoned fee input on CPFP reselect - #1135

Open
github-actions[bot] wants to merge 1 commit into
v0.1.x-branchfrom
backport-1066-to-v0.1.x-branch
Open

[v0.1.x-branch] Backport #1066: txconfirm: release abandoned fee input on CPFP reselect#1135
github-actions[bot] wants to merge 1 commit into
v0.1.x-branchfrom
backport-1066-to-v0.1.x-branch

Conversation

@github-actions

Copy link
Copy Markdown

Backport of #1066


Closes #664.

Problem

In broadcastWithCPFP, when the precise per-input vsize recompute grows
the package fee enough to push the originally selected fee input's change
below the dust limit, the broadcaster reselects a larger fee input — but
it had already reserveFeeInput'd (and wallet-LeaseOutput'd) the
original before the reselect and never released it. The abandoned UTXO
stays reserved and wallet-leased for the parent's whole lifetime (or until
DefaultFeeInputLeaseExpiry), even though the CPFP child only ever spends
the reselected input. It's a spurious UTXO lock (not fund loss) that
starves other fee selections.

Fix

Release the abandoned input's reservation + wallet lease
(releaseFeeOutpoint) when the reselect lands on a different outpoint.

The caveat that makes this non-trivial: selectFeeInput can
legitimately return a carried-over reservation on a fee bump — TRUC
package RBF requires the replacement child to double-spend the previous
child's fee input, so that input must stay reserved. The release therefore
skips a carried-over input: feeOutpointReserved records whether the input
was already reserved before the (idempotent) re-reservation, so a
freshly-selected-and-abandoned input is released while a carried-over one
is left intact.

Testing

TestCPFPReselectReleasesAbandonedFeeInput drives the exact reselect path
(a P2PKH fee input heavier than the OP_TRUE change proxy grows the fee and
forces a reselect off the small UTXO) and asserts the abandoned input is
dropped from the in-memory reservation set and its wallet lease is
released, while the reselected input stays reserved. It fails on main and
passes with the fix. Full txconfirm suite + lint-changed-local green.

🤖 Generated with Claude Code

When the precise per-input vsize recompute grows the package fee enough
to push the selected fee input's change below the dust limit,
broadcastWithCPFP reselects a larger fee input. It had already reserved
and wallet-leased the original input, and never released it: the
abandoned UTXO stayed locked for the parent's whole lifetime (or until
the lease expired) even though the CPFP child only spends the reselected
input, needlessly starving other fee selections (#664).

Release the abandoned input's reservation and wallet lease when the
reselect lands on a different outpoint. The release is skipped for a fee
input carried over from a prior committed bump: TRUC package RBF needs
the replacement child to double-spend the previous child's fee input, so
that input must stay reserved. feeOutpointReserved records the carried-
over state before the (idempotent) re-reservation so the two cases are
told apart.

(cherry picked from commit 8664040)
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