From 5917486dc9a0c5ee23394185cd8b63640268d513 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Mon, 9 Aug 2021 13:55:33 +0200 Subject: [PATCH] channel_notifier: keep chan in SCB on local foce close In case we force close a channel from our end the funds can be time locked for up to 2 weeks worst case. If something happens to our node in that time, we don't have any information on that channel anymore because currently the channel is removed from the channel backup file the moment the commitment transaction confirms. Instead we want to keep the channel around in the SCB file until we've actually swept the time locked funds. It looks like lnd even supports recovering from such a case if the peer is still online and can tell us what commit height to use for deriving the commit point. If the peer isn't around anymore then external tools could be used to brute force the commit height. --- channel_notifier.go | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/channel_notifier.go b/channel_notifier.go index 960ba0d9..02d9e6d2 100644 --- a/channel_notifier.go +++ b/channel_notifier.go @@ -122,12 +122,52 @@ func (c *channelNotifier) SubscribeChans(startingChans map[wire.OutPoint]struct{ // channel to the sub-swapper. case channelnotifier.ClosedChannelEvent: chanPoint := event.CloseSummary.ChanPoint + closeType := event.CloseSummary.CloseType + + // Because we see the contract as closed + // once our local force close TX + // confirms, the channel arbitrator + // already fires on this event. But + // because our funds can be in limbo for + // up to 2 weeks worst case we don't + // want to remove the crucial info we + // need for sweeping that time locked + // output before we've actually done so. + if closeType == channeldb.LocalForceClose { + ltndLog.Debugf("Channel %v "+ + "was force closed by "+ + "us, not removing "+ + "from channel backup "+ + "until fully resolved", + chanPoint) + + continue + } + chanEvent := chanbackup.ChannelEvent{ ClosedChans: []wire.OutPoint{ chanPoint, }, } + select { + case chanUpdates <- chanEvent: + case <-quit: + return + } + + // A channel was fully resolved on chain. This + // should only really interest us if it was a + // locally force closed channel where we didn't + // remove the channel already when the close + // event was fired. + case channelnotifier.FullyResolvedChannelEvent: + chanEvent := chanbackup.ChannelEvent{ + ClosedChans: []wire.OutPoint{ + *event.ChannelPoint, + }, + } + select { case chanUpdates <- chanEvent: case <-quit: