contractcourt: mark channel as borked before removing the link

In this commit, we ensure that we mark the channel as borked before we
remove the link during the force close process. This ensures that if the
peer reconnects right after we remove the link, then it won't be loaded
into memory in `loadActiveChannels`. We'll now:

  * mark the channel as borked
  * remove the link
  * read the channel state from disk
  * force close

This ensures that the link (if it's active) is able to commit any
pending changes to disk before we read out the channel to force close.
This commit is contained in:
Olaoluwa Osuntokun 2019-03-08 16:40:49 -08:00
parent dac35c46f3
commit bc72691806
No known key found for this signature in database
GPG Key ID: CE58F7F8E20FD9A2

@ -227,25 +227,37 @@ func newActiveChannelArbitrator(channel *channeldb.OpenChannel,
ShortChanID: channel.ShortChanID(), ShortChanID: channel.ShortChanID(),
BlockEpochs: blockEpoch, BlockEpochs: blockEpoch,
ForceCloseChan: func() (*lnwallet.LocalForceCloseSummary, error) { ForceCloseChan: func() (*lnwallet.LocalForceCloseSummary, error) {
// With the channels fetched, attempt to locate // First, we mark the channel as borked, this ensure
// the target channel according to its channel // that no new state transitions can happen, and also
// point. // that the link won't be loaded into the switch.
if err := channel.MarkBorked(); err != nil {
return nil, err
}
// With the channel marked as borked, we'll now remove
// the link from the switch if its there. If the link
// is active, then this method will block until it
// exits.
if err := c.cfg.MarkLinkInactive(chanPoint); err != nil {
log.Errorf("unable to mark link inactive: %v", err)
}
// Now that we know the link can't mutate the channel
// state, we'll read the channel from disk the target
// channel according to its channel point.
channel, err := c.chanSource.FetchChannel(chanPoint) channel, err := c.chanSource.FetchChannel(chanPoint)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Finally, we'll force close the channel completing
// the force close workflow.
chanMachine, err := lnwallet.NewLightningChannel( chanMachine, err := lnwallet.NewLightningChannel(
c.cfg.Signer, c.cfg.PreimageDB, channel, nil, c.cfg.Signer, c.cfg.PreimageDB, channel, nil,
) )
if err != nil { if err != nil {
return nil, err return nil, err
} }
if err := c.cfg.MarkLinkInactive(chanPoint); err != nil {
log.Errorf("unable to mark link inactive: %v", err)
}
return chanMachine.ForceClose() return chanMachine.ForceClose()
}, },
MarkCommitmentBroadcasted: channel.MarkCommitmentBroadcasted, MarkCommitmentBroadcasted: channel.MarkCommitmentBroadcasted,