Skip to content

multi: support externally managed channel lifecycles - #11178

Open
sputn1ck wants to merge 4 commits into
lightningnetwork:masterfrom
sputn1ck:kon/modular-channel-runtime
Open

sputn1ck wants to merge 4 commits into
lightningnetwork:masterfrom
sputn1ck:kon/modular-channel-runtime

Conversation

@sputn1ck

@sputn1ck sputn1ck commented Sep 7, 2026

Copy link
Copy Markdown
Collaborator

Change Description

Some custom channel implementations negotiate a normal lnd channel while
another subsystem coordinates how the funding output reaches the chain. They
still need lnd to own channel state, HTLC processing, commitments, and contract
resolution.

This PR exposes the minimal, application-neutral boundaries needed for that
composition:

  • allow a funding coordinator to inspect the exact output negotiated by a
    pending reservation while lnd continues to own its wallet lifecycle;
  • add a synchronous funding-message entry point whose completion includes
    asynchronous ChannelReady processing;
  • add an optional auxiliary channel lifecycle for explicit chain-watch
    ownership, funding materialization before commitment publication, and durable
    terminal cleanup;
  • allow a force close paused at the materialization barrier to be resumed
    safely.

All behavior is opt-in. Without an auxiliary lifecycle, lnd retains its existing
funding dispatch, chain watching, force-close, and cleanup behavior. The
interfaces contain no application-specific policy or types.

Testing

  • go test ./lnwallet ./funding ./contractcourt -count=1
  • go test ./funding -run '^TestProcessFundingMsgAndWait' -race -count=1
  • make fmt-check
  • make tidy-module-check
  • changed-code lint with the repository's custom-gcl against
    lightningnetwork/master

Copilot AI lite review requested due to automatic review settings September 7, 2026 12:43
@sputn1ck
sputn1ck force-pushed the kon/modular-channel-runtime branch from 370bcc8 to e121f7e Compare September 7, 2026 12:44
@github-actions github-actions Bot added the severity-critical Requires expert review - security/consensus critical label Sep 7, 2026
@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown

🔴 PR Severity: CRITICAL

gh pr view | 14 files | 1144 lines changed

🔴 Critical (12 files)
  • contractcourt/aux_channel_lifecycle.go - new file; auxiliary channel lifecycle logic in the on-chain dispute resolution subsystem
  • contractcourt/chain_arbitrator.go - core chain arbitrator logic (breach/dispute handling)
  • contractcourt/chain_arbitrator_test.go - tests accompanying chain arbitrator changes
  • contractcourt/channel_arbitrator.go - core channel arbitrator logic (breach/dispute handling)
  • contractcourt/channel_arbitrator_test.go - tests accompanying channel arbitrator changes
  • funding/manager.go - channel funding workflow coordination
  • funding/manager_test.go - tests accompanying funding manager changes
  • lnwallet/config.go - wallet configuration surface
  • lnwallet/reservation.go - channel funding reservation / commitment construction logic
  • lnwallet/wallet.go - core wallet operations
  • lnwallet/wallet_test.go - tests accompanying wallet changes
  • server.go - core server coordination
🟡 Medium (1 file)
  • config_builder.go - server config wiring (uncategorized Go file)
🟢 Low (1 file)
  • docs/release-notes/release-notes-0.22.0.md - release notes

Analysis

This PR modifies core wallet reservation/commitment logic (lnwallet/reservation.go, lnwallet/wallet.go), the on-chain dispute resolution state machines (contractcourt/chain_arbitrator.go, contractcourt/channel_arbitrator.go, plus a new aux_channel_lifecycle.go), and the channel funding workflow (funding/manager.go), alongside server.go wiring. Each of these packages independently qualifies as CRITICAL, and the PR spans three distinct critical subsystems (wallet, contract court, funding) plus core server coordination. Excluding tests and docs, the change is ~472 lines across 10 files — under the >500 line / >20 file auto-bump thresholds, but the multi-critical-package footprint alone warrants expert review of funding, breach-handling, and wallet reservation invariants.


To override, add a severity-override-{critical,high,medium,low} label.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

A goroutine in ChainArbitrator.resolveContracts captures the cp loop variable, which can cause resolving the wrong channel outpoint under concurrency.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR adds opt-in integration points to let external systems manage parts of a channel’s funding and on-chain lifecycle while lnd continues to own channel state machines (HTLCs, commitments, and contract resolution). It introduces an auxiliary channel lifecycle interface, an externally managed wallet-controller mode, a way to inspect negotiated funding outputs for pending reservations, and a synchronous funding-message delivery path.

Changes:

  • Add an optional AuxChannelLifecycle to coordinate chain-watch ownership, commitment-publication gating, and durable terminal cleanup (with resumable force-close support).
  • Allow embedding runtimes to manage the base WalletController lifecycle and to query the exact negotiated funding output for active reservations.
  • Add ProcessFundingMsgAndWait to synchronously wait for the existing funding-message handler to complete on the coordinator goroutine.
File summaries
File Description
server.go Plumbs AuxChannelLifecycle into server configuration.
lnwallet/config.go Adds ExternallyManagedWalletController config flag.
lnwallet/wallet.go Skips wallet-controller start/stop when externally managed; adds thread-safe reservation inspection APIs.
lnwallet/reservation.go Adds fundingOutput() helper to derive the negotiated funding output.
lnwallet/wallet_test.go Adds tests for externally managed wallet lifecycle and pending funding output lookup.
funding/manager.go Refactors funding message handling and adds synchronous ProcessFundingMsgAndWait.
funding/manager_test.go Adds tests for synchronous funding message admission and completion behavior.
contractcourt/aux_channel_lifecycle.go Introduces the AuxChannelLifecycle interface and chain-watch ownership model.
contractcourt/channel_arbitrator.go Adds commitment-publication barrier and resumable force-close behavior.
contractcourt/channel_arbitrator_test.go Adds tests asserting the publication barrier and resume semantics.
contractcourt/chain_arbitrator.go Adds optional chain-watch admission policy and terminal finalization barrier; parallelizes resolution when enabled.
contractcourt/chain_arbitrator_test.go Adds tests for admission filtering, unknown owner rejection, and finalization barrier behavior.
config_builder.go Exposes AuxChannelLifecycle in aux component configuration.
docs/release-notes/release-notes-0.22.0.md Documents the externally managed funding/lifecycle capability for the release notes.
Review details
  • Files reviewed: 14/14 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +799 to +803
c.wg.Add(1)
go func() {
defer c.wg.Done()
c.resolveContract(cp)
}()
External funding coordinators need the exact output negotiated by a
pending channel reservation. Expose a synchronized lookup by pending
channel ID without changing LightningWallet lifecycle ownership.
@sputn1ck
sputn1ck force-pushed the kon/modular-channel-runtime branch from e121f7e to 05d0ea4 Compare September 8, 2026 09:55
External transports need an unambiguous delivery boundary before they
acknowledge an inbound funding message. Add an opt-in synchronous entry
point while preserving the existing asynchronous path and funding
protocol error reporting.
@sputn1ck
sputn1ck force-pushed the kon/modular-channel-runtime branch from 05d0ea4 to 26c3220 Compare September 9, 2026 10:08
@litbot-9000

Copy link
Copy Markdown
Collaborator

@sputn1ck, remember to re-request review from reviewers when ready

@sputn1ck
sputn1ck force-pushed the kon/modular-channel-runtime branch from c0b4900 to 26a4413 Compare September 15, 2026 17:02
Externally funded channels need explicit chain-watch ownership and
durable barriers around commitment publication and terminal cleanup. Add
one cancelable auxiliary interface and make interrupted force closes
safely resumable.

Keep missing-input sweep failures retryable until a spend notification
arrives. An empty immediate lookup cannot prove an input is orphaned;
canceling its watch can strand a resolver after its sweep confirms.
Expose the driver-independent SQL backend without native driver build
flags. Register PostgreSQL in its backend and preserve walletdb bucket
semantics for SQL drivers that decode empty blobs as nil slices.

Keep shared connections alive when another namespace fails to open.
Cover external driver construction, cursor semantics, and ownership.
@sputn1ck
sputn1ck force-pushed the kon/modular-channel-runtime branch from 26a4413 to 8b853cc Compare September 15, 2026 17:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

severity-critical Requires expert review - security/consensus critical

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants