From 5a285827194f85af10c138da735b35a1faee97aa Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 18 Nov 2021 13:32:27 -0800 Subject: [PATCH] contractcourt: only supplement resolvers if channel has historical state In this commit, we fix a bug that would cause newly updated nodes to be unable to start up, if they have an older channel that was closed before we started to store all the historical state for each channel. The issue is that we started to write the complete state to disk, but newer channels don't have it, so when we try to supplement the resolvers, we run into this error. Ultimately, we only need this new supplemented information for script enforcement channels. Ideally we would instead check the channel type there instead, but it doesn't appear to be available in this context as is, without further changes. Fixes https://github.com/lightningnetwork/lnd/issues/6001. --- contractcourt/channel_arbitrator.go | 42 +++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/contractcourt/channel_arbitrator.go b/contractcourt/channel_arbitrator.go index e85e74b34..ff29e6966 100644 --- a/contractcourt/channel_arbitrator.go +++ b/contractcourt/channel_arbitrator.go @@ -612,8 +612,17 @@ func (c *ChannelArbitrator) relaunchResolvers(commitSet *CommitSet, // We'll also fetch the historical state of this channel, as it should // have been marked as closed by now, and supplement it to each resolver // such that we can properly resolve our pending contracts. - chanState, err := c.cfg.FetchHistoricalChannel() - if err != nil { + var chanState *channeldb.OpenChannel + chanState, err = c.cfg.FetchHistoricalChannel() + switch { + // If we don't find this channel, then it may be the case that it + // was closed before we started to retain the final state + // information for open channels. + case err == channeldb.ErrChannelNotFound: + log.Warnf("ChannelArbitrator(%v): unable to fetch historical "+ + "state", c.cfg.ChanPoint) + + case err != nil: return err } @@ -621,7 +630,9 @@ func (c *ChannelArbitrator) relaunchResolvers(commitSet *CommitSet, "resolvers", c.cfg.ChanPoint, len(unresolvedContracts)) for _, resolver := range unresolvedContracts { - resolver.SupplementState(chanState) + if chanState != nil { + resolver.SupplementState(chanState) + } htlcResolver, ok := resolver.(htlcContractResolver) if !ok { @@ -1930,8 +1941,17 @@ func (c *ChannelArbitrator) prepContractResolutions( // We'll also fetch the historical state of this channel, as it should // have been marked as closed by now, and supplement it to each resolver // such that we can properly resolve our pending contracts. - chanState, err := c.cfg.FetchHistoricalChannel() - if err != nil { + var chanState *channeldb.OpenChannel + chanState, err = c.cfg.FetchHistoricalChannel() + switch { + // If we don't find this channel, then it may be the case that it + // was closed before we started to retain the final state + // information for open channels. + case err == channeldb.ErrChannelNotFound: + log.Warnf("ChannelArbitrator(%v): unable to fetch historical "+ + "state", c.cfg.ChanPoint) + + case err != nil: return nil, nil, err } @@ -2040,7 +2060,9 @@ func (c *ChannelArbitrator) prepContractResolutions( resolver := newTimeoutResolver( resolution, height, htlc, resolverCfg, ) - resolver.SupplementState(chanState) + if chanState != nil { + resolver.SupplementState(chanState) + } htlcResolvers = append(htlcResolvers, resolver) } @@ -2097,7 +2119,9 @@ func (c *ChannelArbitrator) prepContractResolutions( resolver := newOutgoingContestResolver( resolution, height, htlc, resolverCfg, ) - resolver.SupplementState(chanState) + if chanState != nil { + resolver.SupplementState(chanState) + } htlcResolvers = append(htlcResolvers, resolver) } } @@ -2111,7 +2135,9 @@ func (c *ChannelArbitrator) prepContractResolutions( *contractResolutions.CommitResolution, height, c.cfg.ChanPoint, resolverCfg, ) - resolver.SupplementState(chanState) + if chanState != nil { + resolver.SupplementState(chanState) + } htlcResolvers = append(htlcResolvers, resolver) }