From f6c02aec20d4b727b8743281d8b1a0906be0faeb Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Thu, 3 Jan 2019 20:33:33 -0500 Subject: [PATCH 1/3] channeldb/channel_test: use random outpoint when creating new test channels In this commit, we use random outpoints when creating new test channels to ensure we can uniquely identify them. --- channeldb/channel_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/channeldb/channel_test.go b/channeldb/channel_test.go index 97ab7d5bf..7cbde7f23 100644 --- a/channeldb/channel_test.go +++ b/channeldb/channel_test.go @@ -205,7 +205,7 @@ func createTestChannelState(cdb *DB) (*OpenChannel, error) { return &OpenChannel{ ChanType: SingleFunder, ChainHash: key, - FundingOutpoint: *testOutpoint, + FundingOutpoint: wire.OutPoint{Hash: key, Index: rand.Uint32()}, ShortChannelID: chanID, IsInitiator: true, IsPending: true, From 409efd1361e3a0fa918e46cc59146afa4b7ac41a Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Thu, 3 Jan 2019 20:33:34 -0500 Subject: [PATCH 2/3] channeldb/channel_test: add TestFetchWaitingCloseChannels In this commit, we add a test case for FetchWaitingCloseChannels to ensure it behaves as intended. Currently, this test fails due to not fetching channels which are pending to be closed but are also pending to be opened. This will be fixed in the following commit and should allow the test to pass. --- channeldb/channel_test.go | 73 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/channeldb/channel_test.go b/channeldb/channel_test.go index 7cbde7f23..b2e56f83c 100644 --- a/channeldb/channel_test.go +++ b/channeldb/channel_test.go @@ -852,6 +852,79 @@ func TestFetchClosedChannels(t *testing.T) { } } +// TestFetchWaitingCloseChannels ensures that the correct channels that are +// waiting to be closed are returned. +func TestFetchWaitingCloseChannels(t *testing.T) { + t.Parallel() + + const numChannels = 2 + const broadcastHeight = 99 + addr := &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 18555} + + // We'll start by creating two channels within our test database. One of + // them will have their funding transaction confirmed on-chain, while + // the other one will remain unconfirmed. + db, cleanUp, err := makeTestDB() + if err != nil { + t.Fatalf("unable to make test database: %v", err) + } + defer cleanUp() + + channels := make([]*OpenChannel, numChannels) + for i := 0; i < numChannels; i++ { + channel, err := createTestChannelState(db) + if err != nil { + t.Fatalf("unable to create channel: %v", err) + } + err = channel.SyncPending(addr, broadcastHeight) + if err != nil { + t.Fatalf("unable to sync channel: %v", err) + } + channels[i] = channel + } + + // We'll only confirm the first one. + channelConf := lnwire.ShortChannelID{ + BlockHeight: broadcastHeight + 1, + TxIndex: 10, + TxPosition: 15, + } + if err := channels[0].MarkAsOpen(channelConf); err != nil { + t.Fatalf("unable to mark channel as open: %v", err) + } + + // Then, we'll mark the channels as if their commitments were broadcast. + // This would happen in the event of a force close and should make the + // channels enter a state of waiting close. + for _, channel := range channels { + if err := channel.MarkCommitmentBroadcasted(); err != nil { + t.Fatalf("unable to mark commitment broadcast: %v", err) + } + } + + // Now, we'll fetch all the channels waiting to be closed from the + // database. We should expect to see both channels above, even if any of + // them haven't had their funding transaction confirm on-chain. + waitingCloseChannels, err := db.FetchWaitingCloseChannels() + if err != nil { + t.Fatalf("unable to fetch all waiting close channels: %v", err) + } + if len(waitingCloseChannels) != 2 { + t.Fatalf("expected %d channels waiting to be closed, got %d", 2, + len(waitingCloseChannels)) + } + expectedChannels := make(map[wire.OutPoint]struct{}) + for _, channel := range channels { + expectedChannels[channel.FundingOutpoint] = struct{}{} + } + for _, channel := range waitingCloseChannels { + if _, ok := expectedChannels[channel.FundingOutpoint]; !ok { + t.Fatalf("expected channel %v to be waiting close", + channel.FundingOutpoint) + } + } +} + // TestRefreshShortChanID asserts that RefreshShortChanID updates the in-memory // short channel ID of another OpenChannel to reflect a preceding call to // MarkOpen on a different OpenChannel. From 70d3fc640ae6f78057216af059d5ae1503cbcaaa Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Thu, 3 Jan 2019 20:33:35 -0500 Subject: [PATCH 3/3] channeldb/db: prevent filtering channels with unconfirmed close txs In this commit, we address an issue with the FetchWaitingCloseChannels method where it would not properly return channels that are unconfirmed and also have an unconfirmed closing transaction because they were filtered out. We fix this by fetching channels that remain unconfirmed that are also waiting for a confirmed closing transaction. This will allow the recently added test TestFetchWaitingCloseChannels to pass. --- channeldb/db.go | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/channeldb/db.go b/channeldb/db.go index 0f9183185..d71656a72 100644 --- a/channeldb/db.go +++ b/channeldb/db.go @@ -450,9 +450,20 @@ func (d *DB) FetchPendingChannels() ([]*OpenChannel, error) { } // FetchWaitingCloseChannels will return all channels that have been opened, -// but now is waiting for a closing transaction to be confirmed. +// but are now waiting for a closing transaction to be confirmed. +// +// NOTE: This includes channels that are also pending to be opened. func (d *DB) FetchWaitingCloseChannels() ([]*OpenChannel, error) { - return fetchChannels(d, false, true) + waitingClose, err := fetchChannels(d, false, true) + if err != nil { + return nil, err + } + pendingWaitingClose, err := fetchChannels(d, true, true) + if err != nil { + return nil, err + } + + return append(waitingClose, pendingWaitingClose...), nil } // fetchChannels attempts to retrieve channels currently stored in the