Skip to content

lightningd: don't disconnect when sending error for unknown channel_reestablish#8988

Open
vincenzopalazzo wants to merge 2 commits intoElementsProject:masterfrom
vincenzopalazzo:fix/dual-funding-reconnect-loop
Open

lightningd: don't disconnect when sending error for unknown channel_reestablish#8988
vincenzopalazzo wants to merge 2 commits intoElementsProject:masterfrom
vincenzopalazzo:fix/dual-funding-reconnect-loop

Conversation

@vincenzopalazzo
Copy link
Copy Markdown
Collaborator

Summary

  • When receiving WIRE_CHANNEL_REESTABLISH for an unknown channel, send the error without disconnecting
  • Prevents a race where the disconnect arrives before the error, leaving the peer with a stale saved channel in DUALOPEND_OPEN_COMMIT_READY that retries indefinitely

The bug: during dual-funding, if one side saves the channel (reaches DUALOPEND_OPEN_COMMIT_READY) but the other deletes its unsaved copy on disconnect, reconnects create an infinite loop. The saved side sends CHANNEL_REESTABLISH, the other side sends error + disconnect. The disconnect races with the error delivery -- if the peer's dualopend doesn't receive the error before the socket closes, dualopen_errmsg is called with disconnect=false, which calls channel_fail_transient instead of deleting the channel, and the cycle repeats.

By not disconnecting, the error reliably reaches the peer's dualopend, which processes it via peer_failed_received_errmsg(disconnect=true) and properly deletes the stale channel.

Test plan

  • Verify make check-units passes (done locally)
  • CI integration tests, particularly test_disconnect_opener

Fixes #8822

…eestablish

When a peer sends WIRE_CHANNEL_REESTABLISH for a channel we don't know
about (e.g. dual-funding where we deleted the unsaved channel on
disconnect but the peer saved it in DUALOPEND_OPEN_COMMIT_READY), we
send an error and disconnect.  The disconnect races with the error
delivery: the peer's dualopend may not receive the error before the
connection drops, so the channel survives as a transient failure and
the peer retries on every reconnect, creating an infinite loop.

Fix this by sending the error without disconnecting for the
WIRE_CHANNEL_REESTABLISH case, so the peer's dualopend reliably
receives the error and cleans up the stale channel.

Changelog-Fixed: dual-funding reconnect loop when peer doesn't know about a saved channel
Fixes: ElementsProject#8822
Signed-off-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
@madelinevibes madelinevibes added the BOUNTY! 🫰 A bounty is available for this PR label Mar 30, 2026
@madelinevibes madelinevibes added this to the 26.06 milestone Mar 30, 2026
@madelinevibes madelinevibes requested a review from niftynei March 30, 2026 02:35
@madelinevibes madelinevibes added the Status::Ready for Review The work has been completed and is now awaiting evaluation or approval. label Mar 30, 2026
Since we no longer disconnect when receiving a channel_reestablish for
an unknown channel, the test needs to explicitly disconnect and
reconnect after restorefrompeer() so the stub channel triggers the
bogus channel_reestablish flow in peer_connected_hook_final.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

BOUNTY! 🫰 A bounty is available for this PR PLEASE clear CI 🫠 Status::Ready for Review The work has been completed and is now awaiting evaluation or approval.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dual-funding can leave peers unable to reconnect

2 participants