funding: wait for commitment restoration before channel_ready - #11288
Amirhosein wants to merge 2 commits into
Conversation
I moved discovery signaling after NewLightningChannel returns so an early channel_ready cannot start a link during commitment restoration. I also restore the barrier after a restart when MarkAsOpen has been persisted but channel_ready has not yet been processed. I release the signal after restoration errors as well, since the funding goroutine will no longer read the commitment chain. This lets queued peer messages proceed rather than leaving them blocked until shutdown. I added regression coverage for confirmed and zero-conf openings, both with and without restart, and successful and failed restoration. Fixes lightningnetwork#11259.
I added a release note for the channel-opening race fix, including restart handling and release of queued channel_ready messages after restoration errors.
🔴 PR Severity: CRITICAL
🔴 Critical (1 file)
🟢 Low (2 files)
AnalysisThe only non-test, non-doc file touched is To override, add a |
Change Description
I would like to propose this fix for #11259, reordering the release of
discoverySignalrelative to commitment restoration during channel opening.Background & Root Cause
During channel opening, if an incoming
channel_readyis processed before the funding goroutine finishes callinglnwallet.NewLightningChannel(...), a link can be instantiated and process commitment updates (e.g.update_add_htlc+commitment_signed). This can write an unacknowledged remote commitment diff to disk.When the concurrent funding goroutine runs
restoreCommitState, it fetches the unacked remote commitment diff from the database viaRemoteCommitChainTip(). However, the in-memory channel copy passed toNewLightningChannelstill hasRemoteNextRevocation == nil(sinceprocessChannelReadyhas not populated it yet). Dereferencing this nil revocation point duringDeriveCommitmentKeyscauses a latent nil-pointer panic.Changes
handleFundingConfirmationandadvancePendingChannelState. I moved the release ofdiscoverySignalto occur immediately afterlnwallet.NewLightningChannelreturns inadvanceFundingState. This covers both regular confirmed channels and zero-confirmation channels in a unified location.Manager.start(), I restored the barrier for channels wherechannel.IsPending || channel.RemoteNextRevocation == nil. If a node restarted afterMarkAsOpenwas persisted to the database but before commitment restoration orchannel_readyprocessing completed, this ensures an earlychannel_readyfrom a reconnected peer cannot bypass the restoration barrier.lnwallet.NewLightningChannelreturns an error, I ensurediscoverySignalis closed (with an appropriate warning log) before returning, preventing queued peer messages from hanging indefinitely until daemon shutdown.funding/manager_discovery_test.gowith 8 test cases covering both confirmed and zero-conf channels, with and without restart, and across successful and failed restoration paths. The tests use a custom aux leaf-store hook to reliably pause restoration and verify that peerchannel_readymessages remain queued and no link is started until restoration completes.# Bug Fixesindocs/release-notes/release-notes-0.22.0.md.Fixes #11259.
Steps to Test
Reviewers can run the unit tests and targeted integration tests:
I have verified all 8 test cases locally with
-raceand 10 repetitions, and verified that without the fix the assertions fail as expected.Pull Request Checklist
Testing
Code Style and Documentation
[skip ci]in the commit message for small changes.Thank you very much for taking the time to review this PR. I would welcome any feedback or suggestions on the approach!