From bc72691806a182e6fb62684fb60ee1dd4176e688 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 8 Mar 2019 16:40:49 -0800 Subject: [PATCH] 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. --- contractcourt/chain_arbitrator.go | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/contractcourt/chain_arbitrator.go b/contractcourt/chain_arbitrator.go index 76be78731..696ddeb26 100644 --- a/contractcourt/chain_arbitrator.go +++ b/contractcourt/chain_arbitrator.go @@ -227,25 +227,37 @@ func newActiveChannelArbitrator(channel *channeldb.OpenChannel, ShortChanID: channel.ShortChanID(), BlockEpochs: blockEpoch, ForceCloseChan: func() (*lnwallet.LocalForceCloseSummary, error) { - // With the channels fetched, attempt to locate - // the target channel according to its channel - // point. + // First, we mark the channel as borked, this ensure + // that no new state transitions can happen, and also + // 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) if err != nil { return nil, err } + // Finally, we'll force close the channel completing + // the force close workflow. chanMachine, err := lnwallet.NewLightningChannel( c.cfg.Signer, c.cfg.PreimageDB, channel, nil, ) if err != nil { return nil, err } - - if err := c.cfg.MarkLinkInactive(chanPoint); err != nil { - log.Errorf("unable to mark link inactive: %v", err) - } - return chanMachine.ForceClose() }, MarkCommitmentBroadcasted: channel.MarkCommitmentBroadcasted,