diff --git a/fundingmanager_test.go b/fundingmanager_test.go index 38e83f49..dc575074 100644 --- a/fundingmanager_test.go +++ b/fundingmanager_test.go @@ -566,7 +566,7 @@ func openChannel(t *testing.T, alice, bob *testNode, localFundingAmt, return fundingOutPoint } -func assertNumPendingChannels(t *testing.T, node *testNode, expectedNum int) { +func assertNumPendingChannelsBecomes(t *testing.T, node *testNode, expectedNum int) { var numPendingChans int for i := 0; i < testPollNumTries; i++ { // If this is not the first try, sleep before retrying. @@ -590,6 +590,28 @@ func assertNumPendingChannels(t *testing.T, node *testNode, expectedNum int) { expectedNum, numPendingChans) } +func assertNumPendingChannelsRemains(t *testing.T, node *testNode, expectedNum int) { + var numPendingChans int + for i := 0; i < 5; i++ { + // If this is not the first try, sleep before retrying. + if i > 0 { + time.Sleep(200 * time.Millisecond) + } + pendingChannels, err := node.fundingMgr. + cfg.Wallet.Cfg.Database.FetchPendingChannels() + if err != nil { + t.Fatalf("unable to fetch pending channels: %v", err) + } + + numPendingChans = len(pendingChannels) + if numPendingChans != expectedNum { + + t.Fatalf("Expected node to have %d pending channels, had %v", + expectedNum, numPendingChans) + } + } +} + func assertDatabaseState(t *testing.T, node *testNode, fundingOutPoint *wire.OutPoint, expectedState channelOpeningState) { @@ -1160,14 +1182,71 @@ func TestFundingManagerFundingTimeout(t *testing.T) { } // Bob should still be waiting for the channel to open. - assertNumPendingChannels(t, bob, 1) + assertNumPendingChannelsRemains(t, bob, 1) bob.mockNotifier.epochChan <- &chainntnfs.BlockEpoch{ Height: fundingBroadcastHeight + 288, } // Should not be pending anymore. - assertNumPendingChannels(t, bob, 0) + assertNumPendingChannelsBecomes(t, bob, 0) +} + +// TestFundingManagerFundingNotTimeoutInitiator checks that if the user was +// the channel initiator, that it does not timeout when the lnd restarts +func TestFundingManagerFundingNotTimeoutInitiator(t *testing.T) { + + alice, bob := setupFundingManagers(t) + defer tearDownFundingManagers(t, alice, bob) + + // We will consume the channel updates as we go, so no buffering is needed. + updateChan := make(chan *lnrpc.OpenStatusUpdate) + + // Run through the process of opening the channel, up until the funding + // transaction is broadcasted. + _ = openChannel(t, alice, bob, 500000, 0, 1, updateChan, true) + + // Alice will at this point be waiting for the funding transaction to be + // confirmed, so the channel should be considered pending. + pendingChannels, err := alice.fundingMgr.cfg.Wallet.Cfg.Database.FetchPendingChannels() + if err != nil { + t.Fatalf("unable to fetch pending channels: %v", err) + } + if len(pendingChannels) != 1 { + t.Fatalf("Expected Alice to have 1 pending channel, had %v", + len(pendingChannels)) + } + + recreateAliceFundingManager(t, alice) + + // Increase the height to 1 minus the maxWaitNumBlocksFundingConf height + alice.mockNotifier.epochChan <- &chainntnfs.BlockEpoch{ + Height: fundingBroadcastHeight + maxWaitNumBlocksFundingConf - 1, + } + + bob.mockNotifier.epochChan <- &chainntnfs.BlockEpoch{ + Height: fundingBroadcastHeight + maxWaitNumBlocksFundingConf - 1, + } + + // Assert both and Alice and Bob still have 1 pending channels + assertNumPendingChannelsRemains(t, alice, 1) + + assertNumPendingChannelsRemains(t, bob, 1) + + // Increase both Alice and Bob to maxWaitNumBlocksFundingConf height + alice.mockNotifier.epochChan <- &chainntnfs.BlockEpoch{ + Height: fundingBroadcastHeight + maxWaitNumBlocksFundingConf, + } + + bob.mockNotifier.epochChan <- &chainntnfs.BlockEpoch{ + Height: fundingBroadcastHeight + maxWaitNumBlocksFundingConf, + } + + // Since Alice was the initiator, the channel should not have timed out + assertNumPendingChannelsRemains(t, alice, 1) + + // Since Bob was not the initiator, the channel should timeout + assertNumPendingChannelsBecomes(t, bob, 0) } // TestFundingManagerReceiveFundingLockedTwice checks that the fundingManager