Merge pull request #1088 from Roasbeef/chan-close-fix

contractcourt: fix co-op chan close issue by not closing over loop iterator variable
This commit is contained in:
Olaoluwa Osuntokun 2018-04-13 13:41:41 -07:00 committed by GitHub
commit cc08baec63
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 38 additions and 6 deletions

View file

@ -327,19 +327,22 @@ func (c *ChainArbitrator) Start() error {
// For each open channel, we'll configure then launch a corresponding // For each open channel, we'll configure then launch a corresponding
// ChannelArbitrator. // ChannelArbitrator.
for _, channel := range openChannels { for _, channel := range openChannels {
chanPoint := channel.FundingOutpoint
// First, we'll create an active chainWatcher for this channel // First, we'll create an active chainWatcher for this channel
// to ensure that we detect any relevant on chain events. // to ensure that we detect any relevant on chain events.
chainWatcher, err := newChainWatcher( chainWatcher, err := newChainWatcher(
channel, c.cfg.Notifier, c.cfg.PreimageDB, c.cfg.Signer, channel, c.cfg.Notifier, c.cfg.PreimageDB, c.cfg.Signer,
c.cfg.IsOurAddress, func() error { c.cfg.IsOurAddress, func() error {
return c.resolveContract(channel.FundingOutpoint, nil) // TODO(roasbeef): also need to pass in log?
return c.resolveContract(chanPoint, nil)
}, },
) )
if err != nil { if err != nil {
return err return err
} }
c.activeWatchers[channel.FundingOutpoint] = chainWatcher c.activeWatchers[chanPoint] = chainWatcher
channelArb, err := newActiveChannelArbitrator( channelArb, err := newActiveChannelArbitrator(
channel, c, chainWatcher.SubscribeChannelEvents(false), channel, c, chainWatcher.SubscribeChannelEvents(false),
) )
@ -347,7 +350,7 @@ func (c *ChainArbitrator) Start() error {
return err return err
} }
c.activeChannels[channel.FundingOutpoint] = channelArb c.activeChannels[chanPoint] = channelArb
} }
// In addition to the channels that we know to be open, we'll also // In addition to the channels that we know to be open, we'll also

View file

@ -782,11 +782,14 @@ func (c *CooperativeCloseCtx) LogPotentialClose(potentialClose *channeldb.Channe
// pending closed in the database, then launch a goroutine to mark the channel // pending closed in the database, then launch a goroutine to mark the channel
// fully closed upon confirmation. // fully closed upon confirmation.
func (c *CooperativeCloseCtx) Finalize(preferredClose *channeldb.ChannelCloseSummary) error { func (c *CooperativeCloseCtx) Finalize(preferredClose *channeldb.ChannelCloseSummary) error {
log.Infof("Finalizing chan close for ChannelPoint(%v)", chanPoint := c.watcher.chanState.FundingOutpoint
c.watcher.chanState.FundingOutpoint)
log.Infof("Finalizing chan close for ChannelPoint(%v)", chanPoint)
err := c.watcher.chanState.CloseChannel(preferredClose) err := c.watcher.chanState.CloseChannel(preferredClose)
if err != nil { if err != nil {
log.Errorf("closeCtx: unable to close ChannelPoint(%v): %v",
chanPoint, err)
return err return err
} }

View file

@ -234,7 +234,7 @@ func closeChannelAndAssert(ctx context.Context, t *harnessTest,
} }
} }
// Finally, generate a single block, wait for the final close status // We'll now, generate a single block, wait for the final close status
// update, then ensure that the closing transaction was included in the // update, then ensure that the closing transaction was included in the
// block. // block.
block := mineBlocks(t, net, 1)[0] block := mineBlocks(t, net, 1)[0]
@ -246,6 +246,32 @@ func closeChannelAndAssert(ctx context.Context, t *harnessTest,
assertTxInBlock(t, block, closingTxid) assertTxInBlock(t, block, closingTxid)
// Finally, the transaction should no longer be in the pending close
// state as we've just mined a block that should include the closing
// transaction. This only applies for co-op close channels though.
if !force {
err = lntest.WaitPredicate(func() bool {
pendingChansRequest := &lnrpc.PendingChannelsRequest{}
pendingChanResp, err := node.PendingChannels(
ctx, pendingChansRequest,
)
if err != nil {
return false
}
for _, pendingClose := range pendingChanResp.PendingClosingChannels {
if pendingClose.Channel.ChannelPoint == chanPointStr {
return false
}
}
return true
}, time.Second*15)
if err != nil {
t.Fatalf("closing transaction not marked as fully closed")
}
}
return closingTxid return closingTxid
} }