Skip to content

Keep a signed splice through a user abort and follow BOLT 2's RBF feerate rules - #60

Merged
kwsantiago merged 17 commits into
blake2b-unifiedfrom
splicein-signed-inflight
Oct 20, 2026
Merged

kwsantiago merged 17 commits into
blake2b-unifiedfrom
splicein-signed-inflight

Conversation

@kwsantiago

@kwsantiago kwsantiago commented Oct 19, 2026 •

Copy link
Copy Markdown

Running splicein (or a splice script) on a channel while the peer's splice was pending turned it into an RBF announced at a quarter of the intended feerate, and when the peer refused it the plugin's abort_channels made channeld abort the peer's splice, which we had already signed, and fail the channel. These changes keep a signed splice through a user abort and make RBFs of a pending splice follow BOLT 2's feerate rules.

Aborting:

  • channeld never aborts an inflight it has sent tx_signatures for; an abort during a negotiation only drops the candidate that negotiation added.
  • abort_channels refuses a channel whose splice is waiting only on the peer's tx_signatures (pointing at a reconnect, or close), aborts the other channels it was given, and returns them as refused. The splice plugin carries on to unreserve and report its own error when abort_channels fails.
  • lightningd learns the peer's tx_signatures when they arrive on a reestablish resume, so it doesn't refuse an abort it no longer needs to.
  • A confirmed_stfu arriving after its stfu_channels command has gone leaves STFU, or is ignored if a splice command now has the channel, instead of failing the channel or crashing lightningd.
  • channeld forgets a splice_init it refuses, and lightningd frees an inflight's previous locked_scid when channeld updates it.
  • When our broadcast of a splice completes, lightningd answers only the splice_signed that was pending when it was sent, not a splice command started later on the channel, whose caller got a splice_signed reply (the splice plugin crashed on it).

Feerates:

  • The splice plugin sends feerates to lightningd as perkw, and weighs the channel input as channeld does when it checks our fee.
  • Replacing a pending splice needs at least 25/24 of its feerate (or one more where that rounds back): splice_init uses it by default and refuses less, also under check, and refuses more than we'll pay unless force_feerate is set. The plugin takes the floor from listpeerchannels' next_feerate.
  • channeld refuses a peer's splice RBF below that with tx_abort.

Each change has a test that fails without it, in tests/test_splicing.py and bitcoin/test/run-next_funding_feerate.c; dev options --dev-splice-warn-instead-of-sigs, --dev-splice-abort-after-sigs, --dev-splice-rbf-any-feerate and --dev-delay-confirmed-stfu reach the states they need.

Changelog-None

@kwsantiago
kwsantiago force-pushed the splicein-signed-inflight branch from 5b34087 to 6601b0f Compare October 19, 2026 17:28
@kwsantiago
kwsantiago force-pushed the splicein-signed-inflight branch from 6601b0f to 1ce0599 Compare October 19, 2026 23:20
@kwsantiago
kwsantiago merged commit 08ed41d into blake2b-unified Oct 20, 2026
89 of 91 checks passed
@kwsantiago
kwsantiago deleted the splicein-signed-inflight branch October 20, 2026 06:06
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