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.
This commit is contained in:
Olaoluwa Osuntokun 2021-11-18 13:32:27 -08:00 committed by Oliver Gugger
parent 5a5d535dc5
commit 5a28582719
No known key found for this signature in database
GPG key ID: 8E4256593F177720

View file

@ -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)
}