Bitlight Labs Blog
Lightning RGB: Making Channel Closes Observable

Lightning RGB: Making Channel Closes Observable

Close a Lightning channel and watch the node's channel list: the channel is gone the instant the call returns. But the funds are still on their way — the closing transaction has to confirm, timelocked outputs may have to mature and be swept, and on mainnet that journey takes anywhere from an hour to days. During that window the assets show up nowhere: not in the channel list, not yet in the spendable wallet balance.

Users told us exactly how that feels: "my funds vanished."

They didn't vanish. The node just couldn't show them. We (Bitlight Labs) closed this gap in RLN with a dedicated closing view: every channel between "close initiated" and "funds back in the wallet" stays visible, with its exact stage, its remaining outputs, and — for colored channels — the RGB asset amounts and their recovery progress.

A close is a journey, not an event

A channel close walks through distinct stages:

StageWhat's happeningWhat the closing view shows
negotiatingShutdown initiated; in-flight payments still resolvingThe channel's full balances, from the very first moment
broadcastingClosing tx handed to the network, not yet minedFunds held visible while the tx is unconfirmed
confirmingOn-chain; waiting out confirmations (or the force-close delay)The closing txid, plus a per-output block countdown
contestedForce close only: an output genuinely disputed on-chainEach disputed output listed with its own deadline
sweepingMatured funds being collected back into the walletSweep progress until the last output lands

The catch: no single data source inside a Lightning node covers this whole journey. The channel manager knows about the negotiation but forgets the channel the moment the closing transaction is signed. The chain watcher knows about confirmations but keeps resolved records around for roughly four weeks as a safety margin — long after the funds are spendable. The sweeper knows about fund collection but nothing that happens before it. Naively surfacing any one of these either drops the funds from view mid-journey, or shows "closing" ghosts for a month after everything settled.

RLN's closing view stitches the three sources into one timeline and applies real settlement semantics. An entry appears the moment a close begins and disappears exactly when every output — BTC and RGB — is back under wallet control. That yields a clean invariant a wallet can build on:

In the channel list → open. In the closing list → closing, with the exact stage visible. In neither → fully settled.

The RGB twist

RLN carries RGB assets inside Lightning channels, and colored funds add a final act to the close: whenever the channel's asset balance changed hands during its lifetime, the asset returns to the RGB wallet through a sweep transaction of its own. That sweep has a small but important failure mode — it needs a little uncolored BTC for fees, and if the wallet has none, it parks and waits.

The closing view exposes this as its own small state machine. parked is not an error — it is an actionable signal: deposit a small amount of BTC and the node resumes on its own. in_flight carries the sweep transaction id for block-explorer tracking. And a closing entry refuses to disappear while any RGB sweep is unfinished, so colored assets can never silently fall into the old visibility gap.

Our integration tests walk the whole lifecycle end to end — cooperative closes, force closes through the full timelock delay, colored channels with in-flight payments failed mid-close — and assert one thing above all: asset conservation. Every RGB unit that entered a channel is accounted for when its closing entry finally disappears.

None of this is specific to RLN — the three subsystems are stock LDK components; what's missing upstream is the stitching. A lifecycle view of the close is worth having in every Lightning node.

Close a channel on RLN today, and at every block along the way there's an answer to the only question that matters: where are my funds?