diff --git a/channeldb/channel.go b/channeldb/channel.go index 8a67b8a48..b538a7e2a 100644 --- a/channeldb/channel.go +++ b/channeldb/channel.go @@ -956,13 +956,18 @@ func (c *OpenChannel) markBroadcasted(status ChannelStatus, key []byte, c.Lock() defer c.Unlock() - var b bytes.Buffer - if err := WriteElement(&b, closeTx); err != nil { - return err - } + // If a closing tx is provided, we'll generate a closure to write the + // transaction in the appropriate bucket under the given key. + var putClosingTx func(*bbolt.Bucket) error + if closeTx != nil { + var b bytes.Buffer + if err := WriteElement(&b, closeTx); err != nil { + return err + } - putClosingTx := func(chanBucket *bbolt.Bucket) error { - return chanBucket.Put(key, b.Bytes()) + putClosingTx = func(chanBucket *bbolt.Bucket) error { + return chanBucket.Put(key, b.Bytes()) + } } return c.putChanStatus(status, putClosingTx) @@ -1039,6 +1044,11 @@ func (c *OpenChannel) putChanStatus(status ChannelStatus, } for _, f := range fs { + // Skip execution of nil closures. + if f == nil { + continue + } + if err := f(chanBucket); err != nil { return err } diff --git a/channeldb/channel_test.go b/channeldb/channel_test.go index 2d6063565..87d69d3ad 100644 --- a/channeldb/channel_test.go +++ b/channeldb/channel_test.go @@ -897,13 +897,24 @@ func TestFetchWaitingCloseChannels(t *testing.T) { PreviousOutPoint: channel.FundingOutpoint, }, ) + if err := channel.MarkCommitmentBroadcasted(closeTx); err != nil { t.Fatalf("unable to mark commitment broadcast: %v", err) } - // Modify the close tx deterministically and also mark it as - // coop closed. Later we will test that distinct transactions - // are returned for both coop and force closes. + // Now try to marking a coop close with a nil tx. This should + // succeed, but it shouldn't exit when queried. + if err = channel.MarkCoopBroadcasted(nil); err != nil { + t.Fatalf("unable to mark nil coop broadcast: %v", err) + } + _, err := channel.BroadcastedCooperative() + if err != ErrNoCloseTx { + t.Fatalf("expected no closing tx error, got: %v", err) + } + + // Finally, modify the close tx deterministically and also mark + // it as coop closed. Later we will test that distinct + // transactions are returned for both coop and force closes. closeTx.TxIn[0].PreviousOutPoint.Index ^= 1 if err := channel.MarkCoopBroadcasted(closeTx); err != nil { t.Fatalf("unable to mark coop broadcast: %v", err)