diff --git a/chancloser.go b/chancloser.go index 66bae7c3..104a80a6 100644 --- a/chancloser.go +++ b/chancloser.go @@ -201,6 +201,24 @@ func (c *channelCloser) initChanShutdown() (*lnwire.Shutdown, error) { // TODO(roasbeef): err if channel has htlc's? + // Before closing, we'll attempt to send a disable update for the + // channel. We do so before closing the channel as otherwise the current + // edge policy won't be retrievable from the graph. + if err := c.cfg.disableChannel(c.chanPoint); err != nil { + peerLog.Warnf("Unable to disable channel %v on "+ + "close: %v", c.chanPoint, err) + } + + // Before continuing, mark the channel as cooperatively closed with a + // nil txn. Even though we haven't negotiated the final txn, this + // guarantees that our listchannels rpc will be externally consistent, + // and reflect that the channel is being shutdown by the time the + // closing request returns. + err := c.cfg.channel.MarkCoopBroadcasted(nil) + if err != nil { + return nil, err + } + // Before returning the shutdown message, we'll unregister the channel // to ensure that it isn't seen as usable within the system. // @@ -428,14 +446,6 @@ func (c *channelCloser) ProcessCloseMsg(msg lnwire.Message) ([]lnwire.Message, b } c.closingTx = closeTx - // Before closing, we'll attempt to send a disable update for - // the channel. We do so before closing the channel as otherwise - // the current edge policy won't be retrievable from the graph. - if err := c.cfg.disableChannel(c.chanPoint); err != nil { - peerLog.Warnf("Unable to disable channel %v on "+ - "close: %v", c.chanPoint, err) - } - // Before publishing the closing tx, we persist it to the // database, such that it can be republished if something goes // wrong. diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index 56517b82..197eff03 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -32,6 +32,7 @@ import ( "github.com/go-errors/errors" "github.com/lightningnetwork/lnd" "github.com/lightningnetwork/lnd/chanbackup" + "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnrpc/invoicesrpc" "github.com/lightningnetwork/lnd/lnrpc/routerrpc" @@ -332,10 +333,33 @@ func assertChannelClosed(ctx context.Context, t *harnessTest, } chanPointStr := fmt.Sprintf("%v:%v", txid, fundingChanPoint.OutputIndex) + // If the channel appears in list channels, ensure that its state + // contains ChanStatusCoopBroadcasted. + ctxt, _ := context.WithTimeout(ctx, defaultTimeout) + listChansRequest := &lnrpc.ListChannelsRequest{} + listChansResp, err := node.ListChannels(ctxt, listChansRequest) + if err != nil { + t.Fatalf("unable to query for list channels: %v", err) + } + for _, channel := range listChansResp.Channels { + // Skip other channels. + if channel.ChannelPoint != chanPointStr { + continue + } + + // Assert that the channel is in coop broadcasted. + if !strings.Contains(channel.ChanStatusFlags, + channeldb.ChanStatusCoopBroadcasted.String()) { + t.Fatalf("channel not coop broadcasted, "+ + "got: %v", channel.ChanStatusFlags) + } + } + // At this point, the channel should now be marked as being in the // state of "waiting close". + ctxt, _ = context.WithTimeout(ctx, defaultTimeout) pendingChansRequest := &lnrpc.PendingChannelsRequest{} - pendingChanResp, err := node.PendingChannels(ctx, pendingChansRequest) + pendingChanResp, err := node.PendingChannels(ctxt, pendingChansRequest) if err != nil { t.Fatalf("unable to query for pending channels: %v", err) }