Skip to content

Return the interactive-tx send error instead of hanging splice_update - #9605

Open
vincenzopalazzo wants to merge 1 commit into
ElementsProject:masterfrom
vincenzopalazzo:repro/issue-9599-splice-update-hang
Open

vincenzopalazzo wants to merge 1 commit into
ElementsProject:masterfrom
vincenzopalazzo:repro/issue-9599-splice-update-hang

Conversation

@vincenzopalazzo

@vincenzopalazzo vincenzopalazzo commented Oct 7, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • splice_update hung after the peer answered the first tx_add_input with tx_complete and then nothing else went out. Fixes splice_update hangs and never returns, even after disconnecting peer #9599.
  • Reproduced on current master (019a5e190). The turn loop in process_interactivetx_updates discarded the error from send_next. The shared funding input is built by channeld, so that first turn succeeds. The user's input needs the previous transaction in the PSBT. utxoupdatepsbt only fills witness_utxo, so the next send fails, nothing is written, and channeld blocked in peer_read.
  • Return that error. splice_update now fails with interactivetx ADD_INPUT PSBT needs the previous transaction set instead of staying pending. No disconnect is required.
  • A peer tx_complete is still just one turn. We do not finalize the splice there.

Test plan

  • test_splice_update_missing_prevtx on current master: strip PSBT_IN_NON_WITNESS_UTXO from the user's input and splice_update returns RpcError matching previous transaction
  • test_splice still completes a normal splice
  • CI

@vincenzopalazzo vincenzopalazzo changed the title Fail splice_update when the peer dies after tx_complete Return the interactive-tx send error instead of hanging splice_update Oct 7, 2026
@vincenzopalazzo
vincenzopalazzo force-pushed the repro/issue-9599-splice-update-hang branch from 274271d to 6c3047c Compare October 7, 2026 21:23
The turn loop discarded the error from sending the next change. If that
send failed, nothing went out and channeld blocked in peer_read waiting
for a peer that had already sent tx_complete.

That is the splice_update hang in ElementsProject#9599. The shared funding input is
built by channeld, so the first turn succeeds. The user's input needs
the previous transaction, which bitcoind's utxoupdatepsbt does not put
in the PSBT, so the next send fails and the RPC never returned.

Changelog-Fixed: splice: `splice_update` returns an error instead of hanging when a contributed input has no previous transaction.
@vincenzopalazzo
vincenzopalazzo force-pushed the repro/issue-9599-splice-update-hang branch from 6c3047c to d05e7fe Compare October 7, 2026 21:54
@ksedgwic

Copy link
Copy Markdown
Collaborator

Concept ACK: the one-line change is the right fix for #9599.
channeld builds the shared input, so the first turn goes out and the peer answers tx_complete; on the second turn the user's input fails the in->input.utxo check in send_next. With the return value dropped nothing was written and the loop went back to peer_read.

Two suggestions before merge:

  1. Exit path: suggest rejecting the PSBT in lightningd at splice_init and splice_update instead of exiting through a warning.
    Today the error reaches splice_initiator_user_update, which calls peer_failed_warn: channeld exits, the peer gets a warning and the connection is dropped. The RPC returns only because the warning is the disconnect case in channel_control_errmsg. A check in json_splice_init and json_splice_update (every input other than the channel's funding outpoint needs psbt->inputs[i].utxo, else SPLICE_INPUT_ERROR) fails the RPC before anything reaches channeld: nothing goes on the wire, the peer is still waiting, and splice_update can be retried with a corrected PSBT or the splice aborted. The interactivetx change stays as the backstop.

  2. Test: suggest asserting the channel is usable after the error, and optionally building the PSBT the way the report did.
    With the current exit channeld dies, so the test could wait for the reconnect and then complete a normal splice. bitcoind.rpc.createpsbt on a listfunds output followed by utxoupdatepsbt gives the witness_utxo-only shape from the report directly, without the PSBT walker.

Separate from this PR: the forced-disconnect half of #9599 is still open, because the pending splice command is only failed on the warning path.
channel_control_errmsg fails it only when disconnect is set, and force_peer_disconnect goes through channel_set_owner(NULL) to subd_release_channel, which clears sd->channel before freeing, so no errcb runs. Once channeld is gone the splice state is gone with it, so the pending command can be failed on every channeld exit.

CI did not run on d05e7fe; both runs were cancelled at start.

This branch has not been deployed

No deployments
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.

splice_update hangs and never returns, even after disconnecting peer

2 participants