diff --git a/fundingmanager_test.go b/fundingmanager_test.go index 66bc6c24..bf4fe291 100644 --- a/fundingmanager_test.go +++ b/fundingmanager_test.go @@ -143,12 +143,27 @@ func createTestWallet(cdb *channeldb.DB, netParams *chaincfg.Params, return wallet, nil } -func createTestFundingManager(t *testing.T, pubKey *btcec.PublicKey, - tempTestDir string, hdSeed []byte, netParams *chaincfg.Params, - chainNotifier chainntnfs.ChainNotifier, estimator lnwallet.FeeEstimator, - sentMessages chan lnwire.Message, sentAnnouncements chan lnwire.Message, - publTxChan chan *wire.MsgTx, shutdownChan chan struct{}, - arbiterChan chan *lnwallet.LightningChannel, fundingPeer *peer) (*fundingManager, error) { +func createTestFundingManager(t *testing.T, privKey *btcec.PrivateKey, + tempTestDir string) (*testNode, error) { + + netParams := activeNetParams.Params + estimator := lnwallet.StaticFeeEstimator{FeeRate: 250} + + chainNotifier := &mockNotifier{ + confChannel: make(chan *chainntnfs.TxConfirmation, 1), + epochChan: make(chan *chainntnfs.BlockEpoch, 1), + } + + newChannelsChan := make(chan *newChannelMsg) + p := &peer{ + newChannels: newChannelsChan, + } + + sentMessages := make(chan lnwire.Message) + sentAnnouncements := make(chan lnwire.Message) + publTxChan := make(chan *wire.MsgTx, 1) + arbiterChan := make(chan *lnwallet.LightningChannel) + shutdownChan := make(chan struct{}) wc := &mockWalletController{ rootKey: alicePrivKey, @@ -174,7 +189,7 @@ func createTestFundingManager(t *testing.T, pubKey *btcec.PublicKey, var chanIDSeed [32]byte f, err := newFundingManager(fundingConfig{ - IDKey: pubKey, + IDKey: privKey.PubKey(), Wallet: lnw, Notifier: chainNotifier, FeeEstimator: estimator, @@ -201,8 +216,11 @@ func createTestFundingManager(t *testing.T, pubKey *btcec.PublicKey, } return nil }, + NotifyWhenOnline: func(peer *btcec.PublicKey, connectedChan chan<- struct{}) { + t.Fatalf("did not expect fundingManager to call NotifyWhenOnline") + }, FindPeer: func(peerKey *btcec.PublicKey) (*peer, error) { - return fundingPeer, nil + return p, nil }, TempChanIDSeed: chanIDSeed, FindChannel: func(chanID lnwire.ChannelID) (*lnwallet.LightningChannel, error) { @@ -236,7 +254,22 @@ func createTestFundingManager(t *testing.T, pubKey *btcec.PublicKey, t.Fatalf("failed creating fundingManager: %v", err) } - return f, nil + if err = f.Start(); err != nil { + t.Fatalf("failed starting fundingManager: %v", err) + } + + return &testNode{ + privKey: privKey, + msgChan: sentMessages, + announceChan: sentAnnouncements, + arbiterChan: arbiterChan, + publTxChan: publTxChan, + fundingMgr: f, + peer: p, + mockNotifier: chainNotifier, + testDir: tempTestDir, + shutdownChannel: shutdownChan, + }, nil } func recreateAliceFundingManager(t *testing.T, alice *testNode) { @@ -282,6 +315,9 @@ func recreateAliceFundingManager(t *testing.T, alice *testNode) { } return nil }, + NotifyWhenOnline: func(peer *btcec.PublicKey, connectedChan chan<- struct{}) { + t.Fatalf("did not expect fundingManager to call NotifyWhenOnline") + }, FindPeer: oldCfg.FindPeer, TempChanIDSeed: oldCfg.TempChanIDSeed, FindChannel: oldCfg.FindChannel, @@ -307,101 +343,26 @@ func setupFundingManagers(t *testing.T) (*testNode, *testNode) { MaxPendingChannels: defaultMaxPendingChannels, } - netParams := activeNetParams.Params - estimator := lnwallet.StaticFeeEstimator{FeeRate: 250} - - aliceNewChannelsChan := make(chan *newChannelMsg) - alicePeer := &peer{ - newChannels: aliceNewChannelsChan, - } - - bobNewChannelsChan := make(chan *newChannelMsg) - bobPeer := &peer{ - newChannels: bobNewChannelsChan, - } - - aliceMockNotifier := &mockNotifier{ - confChannel: make(chan *chainntnfs.TxConfirmation, 1), - epochChan: make(chan *chainntnfs.BlockEpoch, 1), - } - aliceTestDir, err := ioutil.TempDir("", "alicelnwallet") if err != nil { t.Fatalf("unable to create temp directory: %v", err) } - aliceMsgChan := make(chan lnwire.Message) - aliceAnnounceChan := make(chan lnwire.Message) - alicePublTxChan := make(chan *wire.MsgTx, 1) - aliceArbiterChan := make(chan *lnwallet.LightningChannel) - aliceShutdownChannel := make(chan struct{}) - - aliceFundingMgr, err := createTestFundingManager(t, alicePubKey, - aliceTestDir, alicePrivKeyBytes[:], netParams, aliceMockNotifier, - estimator, aliceMsgChan, aliceAnnounceChan, alicePublTxChan, - aliceShutdownChannel, aliceArbiterChan, alicePeer) + alice, err := createTestFundingManager(t, alicePrivKey, aliceTestDir) if err != nil { t.Fatalf("failed creating fundingManager: %v", err) } - if err = aliceFundingMgr.Start(); err != nil { - t.Fatalf("failed starting fundingManager: %v", err) - } - - alice := &testNode{ - privKey: alicePrivKey, - msgChan: aliceMsgChan, - announceChan: aliceAnnounceChan, - arbiterChan: aliceArbiterChan, - publTxChan: alicePublTxChan, - fundingMgr: aliceFundingMgr, - peer: alicePeer, - mockNotifier: aliceMockNotifier, - testDir: aliceTestDir, - shutdownChannel: aliceShutdownChannel, - } - - bobMockNotifier := &mockNotifier{ - confChannel: make(chan *chainntnfs.TxConfirmation, 1), - epochChan: make(chan *chainntnfs.BlockEpoch, 1), - } - bobTestDir, err := ioutil.TempDir("", "boblnwallet") if err != nil { t.Fatalf("unable to create temp directory: %v", err) } - bobMsgChan := make(chan lnwire.Message) - bobAnnounceChan := make(chan lnwire.Message) - bobPublTxChan := make(chan *wire.MsgTx, 1) - bobArbiterChan := make(chan *lnwallet.LightningChannel) - bobShutdownChannel := make(chan struct{}) - - bobFundingMgr, err := createTestFundingManager(t, bobPubKey, bobTestDir, - bobPrivKeyBytes[:], netParams, bobMockNotifier, estimator, - bobMsgChan, bobAnnounceChan, bobPublTxChan, shutdownChannel, - bobArbiterChan, bobPeer) + bob, err := createTestFundingManager(t, bobPrivKey, bobTestDir) if err != nil { t.Fatalf("failed creating fundingManager: %v", err) } - if err = bobFundingMgr.Start(); err != nil { - t.Fatalf("failed starting fundingManager: %v", err) - } - - bob := &testNode{ - privKey: bobPrivKey, - msgChan: bobMsgChan, - announceChan: bobAnnounceChan, - arbiterChan: bobArbiterChan, - publTxChan: bobPublTxChan, - fundingMgr: bobFundingMgr, - peer: bobPeer, - mockNotifier: bobMockNotifier, - testDir: bobTestDir, - shutdownChannel: bobShutdownChannel, - } - return alice, bob } @@ -559,30 +520,8 @@ func openChannel(t *testing.T, alice, bob *testNode, localFundingAmt, return fundingOutPoint } -func TestFundingManagerNormalWorkflow(t *testing.T) { - disableFndgLogger(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. - fundingOutPoint := openChannel(t, alice, bob, 500000, 0, 1, updateChan) - - // Notify that transaction was mined - alice.mockNotifier.confChannel <- &chainntnfs.TxConfirmation{} - bob.mockNotifier.confChannel <- &chainntnfs.TxConfirmation{} - - // Give fundingManager time to process the newly mined tx and write - //state to database. - time.Sleep(300 * time.Millisecond) - - // The funding transaction was mined, so assert that both funding - // managers now have the state of this channel 'markedOpen' in their - // internal state machine. +func assertMarkedOpen(t *testing.T, alice, bob *testNode, + fundingOutPoint *wire.OutPoint) { state, _, err := alice.fundingMgr.getChannelOpeningState(fundingOutPoint) if err != nil { t.Fatalf("unable to get channel state: %v", err) @@ -599,53 +538,33 @@ func TestFundingManagerNormalWorkflow(t *testing.T) { if state != markedOpen { t.Fatalf("expected state to be markedOpen, was %v", state) } +} - // After the funding transaction is mined, Alice will send - // fundingLocked to Bob. - var aliceMsg lnwire.Message +func checkNodeSendingFundingLocked(t *testing.T, node *testNode) *lnwire.FundingLocked { + var msg lnwire.Message select { - case aliceMsg = <-alice.msgChan: + case msg = <-node.msgChan: case <-time.After(time.Second * 5): - t.Fatalf("alice did not send fundingLocked") + t.Fatalf("node did not send fundingLocked") } - fundingLockedAlice, ok := aliceMsg.(*lnwire.FundingLocked) + fundingLocked, ok := msg.(*lnwire.FundingLocked) if !ok { - errorMsg, gotError := aliceMsg.(*lnwire.Error) + errorMsg, gotError := msg.(*lnwire.Error) if gotError { t.Fatalf("expected FundingLocked to be sent "+ - "from alice, instead got error: %v", + "from node, instead got error: %v", lnwire.ErrorCode(errorMsg.Data[0])) } - t.Fatalf("expected FundingLocked to be sent from alice, "+ - "instead got %T", aliceMsg) + t.Fatalf("expected FundingLocked to be sent from node, "+ + "instead got %T", msg) } + return fundingLocked +} - // And similarly Bob will send funding locked to Alice. - var bobMsg lnwire.Message - select { - case bobMsg = <-bob.msgChan: - case <-time.After(time.Second * 5): - t.Fatalf("bob did not send fundingLocked") - } - - fundingLockedBob, ok := bobMsg.(*lnwire.FundingLocked) - if !ok { - errorMsg, gotError := bobMsg.(*lnwire.Error) - if gotError { - t.Fatalf("expected FundingLocked to be sent "+ - "from bob, instead got error: %v", - lnwire.ErrorCode(errorMsg.Data[0])) - } - t.Fatalf("expected FundingLocked to be sent from bob, "+ - "instead got %T", bobMsg) - } - - // Sleep to make sure database write is finished. - time.Sleep(300 * time.Millisecond) - - // Check that the state machine is updated accordingly - state, _, err = alice.fundingMgr.getChannelOpeningState(fundingOutPoint) +func assertFundingLockedSent(t *testing.T, alice, bob *testNode, + fundingOutPoint *wire.OutPoint) { + state, _, err := alice.fundingMgr.getChannelOpeningState(fundingOutPoint) if err != nil { t.Fatalf("unable to get channel state: %v", err) } @@ -661,7 +580,9 @@ func TestFundingManagerNormalWorkflow(t *testing.T) { if state != fundingLockedSent { t.Fatalf("expected state to be fundingLockedSent, was %v", state) } +} +func assertChannelAnnouncements(t *testing.T, alice, bob *testNode) { // After the FundingLocked message is sent, the channel will be announced. // A chanAnnouncement consists of three distinct messages: // 1) ChannelAnnouncement @@ -748,9 +669,9 @@ func TestFundingManagerNormalWorkflow(t *testing.T) { if !gotNodeAnnouncement { t.Fatalf("did not get NodeAnnouncement from Bob") } +} - // The funding process is now finished, wait for the - // OpenStatusUpdate_ChanOpen update +func waitForOpenUpdate(t *testing.T, updateChan chan *lnrpc.OpenStatusUpdate) { var openUpdate *lnrpc.OpenStatusUpdate select { case openUpdate = <-updateChan: @@ -758,30 +679,27 @@ func TestFundingManagerNormalWorkflow(t *testing.T) { t.Fatalf("alice did not send OpenStatusUpdate") } - _, ok = openUpdate.Update.(*lnrpc.OpenStatusUpdate_ChanOpen) + _, ok := openUpdate.Update.(*lnrpc.OpenStatusUpdate_ChanOpen) if !ok { t.Fatal("OpenStatusUpdate was not OpenStatusUpdate_ChanOpen") } +} - // The internal state-machine should now have deleted the channelStates - // from the database, as the channel is announced. - state, _, err = alice.fundingMgr.getChannelOpeningState(fundingOutPoint) +func assertNoChannelState(t *testing.T, alice, bob *testNode, + fundingOutPoint *wire.OutPoint) { + state, _, err := alice.fundingMgr.getChannelOpeningState(fundingOutPoint) if err != ErrChannelNotFound { t.Fatalf("expected to not find channel state, but got: %v", state) } - // Need to give bob time to update database. - time.Sleep(300 * time.Millisecond) - state, _, err = bob.fundingMgr.getChannelOpeningState(fundingOutPoint) if err != ErrChannelNotFound { t.Fatalf("expected to not find channel state, but got: %v", state) } - // Exchange the fundingLocked messages. - alice.fundingMgr.processFundingLocked(fundingLockedBob, bobAddr) - bob.fundingMgr.processFundingLocked(fundingLockedAlice, aliceAddr) +} +func assertHandleFundingLocked(t *testing.T, alice, bob *testNode) { // They should both send the new channel to the breach arbiter. select { case <-alice.arbiterChan: @@ -809,7 +727,66 @@ func TestFundingManagerNormalWorkflow(t *testing.T) { case <-time.After(time.Second * 5): t.Fatalf("bob did not send new channel to peer") } +} +func TestFundingManagerNormalWorkflow(t *testing.T) { + disableFndgLogger(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. + fundingOutPoint := openChannel(t, alice, bob, 500000, 0, 1, updateChan) + + // Notify that transaction was mined + alice.mockNotifier.confChannel <- &chainntnfs.TxConfirmation{} + bob.mockNotifier.confChannel <- &chainntnfs.TxConfirmation{} + + // Give fundingManager time to process the newly mined tx and write + //state to database. + time.Sleep(300 * time.Millisecond) + + // The funding transaction was mined, so assert that both funding + // managers now have the state of this channel 'markedOpen' in their + // internal state machine. + assertMarkedOpen(t, alice, bob, fundingOutPoint) + + // After the funding transaction is mined, Alice will send + // fundingLocked to Bob. + fundingLockedAlice := checkNodeSendingFundingLocked(t, alice) + + // And similarly Bob will send funding locked to Alice. + fundingLockedBob := checkNodeSendingFundingLocked(t, bob) + + // Sleep to make sure database write is finished. + time.Sleep(300 * time.Millisecond) + + // Check that the state machine is updated accordingly + assertFundingLockedSent(t, alice, bob, fundingOutPoint) + + // Make sure both fundingManagers send the expected channel announcements. + assertChannelAnnouncements(t, alice, bob) + + // The funding process is now finished, wait for the + // OpenStatusUpdate_ChanOpen update + waitForOpenUpdate(t, updateChan) + + // The internal state-machine should now have deleted the channelStates + // from the database, as the channel is announced. + time.Sleep(300 * time.Millisecond) + assertNoChannelState(t, alice, bob, fundingOutPoint) + + // Exchange the fundingLocked messages. + alice.fundingMgr.processFundingLocked(fundingLockedBob, bobAddr) + bob.fundingMgr.processFundingLocked(fundingLockedAlice, aliceAddr) + + // Check that they notify the breach arbiter and peer about the new + // channel. + assertHandleFundingLocked(t, alice, bob) } func TestFundingManagerRestartBehavior(t *testing.T) { @@ -828,12 +805,15 @@ func TestFundingManagerRestartBehavior(t *testing.T) { // before this message has been successfully sent, it should retry // sending it on restart. We mimic this behavior by letting the // SendToPeer method return an error, as if the message was not - // successfully sent. We then the fundingManager and make sure + // successfully sent. We then recreate the fundingManager and make sure // it continues the process as expected. alice.fundingMgr.cfg.SendToPeer = func(target *btcec.PublicKey, msgs ...lnwire.Message) error { return fmt.Errorf("intentional error in SendToPeer") } + alice.fundingMgr.cfg.NotifyWhenOnline = func(peer *btcec.PublicKey, con chan<- struct{}) { + // Intetionally empty. + } // Notify that transaction was mined alice.mockNotifier.confChannel <- &chainntnfs.TxConfirmation{} @@ -846,22 +826,7 @@ func TestFundingManagerRestartBehavior(t *testing.T) { // The funding transaction was mined, so assert that both funding // managers now have the state of this channel 'markedOpen' in their // internal state machine. - state, _, err := alice.fundingMgr.getChannelOpeningState(fundingOutPoint) - if err != nil { - t.Fatalf("unable to get channel state: %v", err) - } - - if state != markedOpen { - t.Fatalf("expected state to be markedOpen, was %v", state) - } - state, _, err = bob.fundingMgr.getChannelOpeningState(fundingOutPoint) - if err != nil { - t.Fatalf("unable to get channel state: %v", err) - } - - if state != markedOpen { - t.Fatalf("expected state to be markedOpen, was %v", state) - } + assertMarkedOpen(t, alice, bob, fundingOutPoint) // After the funding transaction was mined, Bob should have successfully // sent the fundingLocked message, while Alice failed sending it. In @@ -874,31 +839,14 @@ func TestFundingManagerRestartBehavior(t *testing.T) { // Expected. } - // Bob will send funding locked to Alice - var bobMsg lnwire.Message - select { - case bobMsg = <-bob.msgChan: - case <-time.After(time.Second * 5): - t.Fatalf("bob did not send fundingLocked") - } - - fundingLockedBob, ok := bobMsg.(*lnwire.FundingLocked) - if !ok { - errorMsg, gotError := bobMsg.(*lnwire.Error) - if gotError { - t.Fatalf("expected FundingLocked to be sent "+ - "from bob, instead got error: %v", - lnwire.ErrorCode(errorMsg.Data[0])) - } - t.Fatalf("expected FundingLocked to be sent from bob, "+ - "instead got %T", bobMsg) - } + // Bob will send funding locked to Alice. + fundingLockedBob := checkNodeSendingFundingLocked(t, bob) // Sleep to make sure database write is finished. time.Sleep(1 * time.Second) // Alice should still be markedOpen - state, _, err = alice.fundingMgr.getChannelOpeningState(fundingOutPoint) + state, _, err := alice.fundingMgr.getChannelOpeningState(fundingOutPoint) if err != nil { t.Fatalf("unable to get channel state: %v", err) } @@ -927,24 +875,7 @@ func TestFundingManagerRestartBehavior(t *testing.T) { return fmt.Errorf("intentional error in SendAnnouncement") } - var aliceMsg lnwire.Message - select { - case aliceMsg = <-alice.msgChan: - case <-time.After(time.Second * 5): - t.Fatalf("alice did not send fundingLocked") - } - - fundingLockedAlice, ok := aliceMsg.(*lnwire.FundingLocked) - if !ok { - errorMsg, gotError := aliceMsg.(*lnwire.Error) - if gotError { - t.Fatalf("expected FundingLocked to be sent "+ - "from alice, instead got error: %v", - lnwire.ErrorCode(errorMsg.Data[0])) - } - t.Fatalf("expected FundingLocked to be sent from alice, "+ - "instead got %T", aliceMsg) - } + fundingLockedAlice := checkNodeSendingFundingLocked(t, alice) // Sleep to make sure database write is finished. time.Sleep(500 * time.Millisecond) @@ -967,138 +898,179 @@ func TestFundingManagerRestartBehavior(t *testing.T) { // Expected } - // Bob, however, should send the announcements - announcements := make([]lnwire.Message, 4) - for i := 0; i < len(announcements); i++ { - select { - case announcements[i] = <-bob.announceChan: - case <-time.After(time.Second * 5): - t.Fatalf("alice did not send announcement %v", i) - } - } - - gotChannelAnnouncement := false - gotChannelUpdate := false - gotAnnounceSignatures := false - gotNodeAnnouncement := false - - for _, msg := range announcements { - switch msg.(type) { - case *lnwire.ChannelAnnouncement: - gotChannelAnnouncement = true - case *lnwire.ChannelUpdate: - gotChannelUpdate = true - case *lnwire.AnnounceSignatures: - gotAnnounceSignatures = true - case *lnwire.NodeAnnouncement: - gotNodeAnnouncement = true - } - } - - if !gotChannelAnnouncement { - t.Fatalf("did not get ChannelAnnouncement from Bob") - } - if !gotChannelUpdate { - t.Fatalf("did not get ChannelUpdate from Bob") - } - if !gotAnnounceSignatures { - t.Fatalf("did not get AnnounceSignatures from Bob") - } - if !gotNodeAnnouncement { - t.Fatalf("did not get NodeAnnouncement from Bob") - } - // Next up, we check that the Alice rebroadcasts the announcement - // messages on restart. + // messages on restart. Bob should as expected send announcements. recreateAliceFundingManager(t, alice) time.Sleep(300 * time.Millisecond) - for i := 0; i < len(announcements); i++ { - select { - case announcements[i] = <-alice.announceChan: - case <-time.After(time.Second * 5): - t.Fatalf("alice did not send announcement %v", i) - } - } - - gotChannelAnnouncement = false - gotChannelUpdate = false - gotAnnounceSignatures = false - gotNodeAnnouncement = false - - for _, msg := range announcements { - switch msg.(type) { - case *lnwire.ChannelAnnouncement: - gotChannelAnnouncement = true - case *lnwire.ChannelUpdate: - gotChannelUpdate = true - case *lnwire.AnnounceSignatures: - gotAnnounceSignatures = true - case *lnwire.NodeAnnouncement: - gotNodeAnnouncement = true - } - } - - if !gotChannelAnnouncement { - t.Fatalf("did not get ChannelAnnouncement from Alice after restart") - } - if !gotChannelUpdate { - t.Fatalf("did not get ChannelUpdate from Alice after restart") - } - if !gotAnnounceSignatures { - t.Fatalf("did not get AnnounceSignatures from Alice after restart") - } - if !gotNodeAnnouncement { - t.Fatalf("did not get NodeAnnouncement from Alice after restart") - } + assertChannelAnnouncements(t, alice, bob) // The funding process is now finished. Since we recreated the // fundingManager, we don't have an update channel to synchronize on, // so a small sleep makes sure the database writing is finished. time.Sleep(300 * time.Millisecond) - // The internal state-machine should now have deleted them from the - // internal database, as the channel is announced. - state, _, err = alice.fundingMgr.getChannelOpeningState(fundingOutPoint) - if err != ErrChannelNotFound { - t.Fatalf("expected to not find channel state, but got: %v", state) - } - - state, _, err = bob.fundingMgr.getChannelOpeningState(fundingOutPoint) - if err != ErrChannelNotFound { - t.Fatalf("expected to not find channel state, but got: %v", state) - } + // The internal state-machine should now have deleted the channelStates + // from the database, as the channel is announced. + assertNoChannelState(t, alice, bob, fundingOutPoint) // Exchange the fundingLocked messages. alice.fundingMgr.processFundingLocked(fundingLockedBob, bobAddr) bob.fundingMgr.processFundingLocked(fundingLockedAlice, aliceAddr) - // They should both send the new channel to the breach arbiter. + // Check that they notify the breach arbiter and peer about the new + // channel. + assertHandleFundingLocked(t, alice, bob) + +} + +// TestFundingManagerOfflinePeer checks that the fundingManager waits for the +// server to notify when the peer comes online, in case sending the +// fundingLocked message fails the first time. +func TestFundingManagerOfflinePeer(t *testing.T) { + disableFndgLogger(t) + + alice, bob := setupFundingManagers(t) + defer tearDownFundingManagers(t, alice, bob) + + // Run through the process of opening the channel, up until the funding + // transaction is broadcasted. + updateChan := make(chan *lnrpc.OpenStatusUpdate) + fundingOutPoint := openChannel(t, alice, bob, 500000, 0, 1, updateChan) + + // After the funding transaction gets mined, both nodes will send the + // fundingLocked message to the other peer. If the funding node fails + // to send the fundingLocked message to the peer, it should wait for + // the server to notify it that the peer is back online, and try again. + alice.fundingMgr.cfg.SendToPeer = func(target *btcec.PublicKey, + msgs ...lnwire.Message) error { + return fmt.Errorf("intentional error in SendToPeer") + } + peerChan := make(chan *btcec.PublicKey, 1) + conChan := make(chan chan<- struct{}, 1) + alice.fundingMgr.cfg.NotifyWhenOnline = func(peer *btcec.PublicKey, connected chan<- struct{}) { + peerChan <- peer + conChan <- connected + } + + // Notify that transaction was mined + alice.mockNotifier.confChannel <- &chainntnfs.TxConfirmation{} + bob.mockNotifier.confChannel <- &chainntnfs.TxConfirmation{} + + // Give fundingManager time to process the newly mined tx and write to + // the database. + time.Sleep(500 * time.Millisecond) + + // The funding transaction was mined, so assert that both funding + // managers now have the state of this channel 'markedOpen' in their + // internal state machine. + assertMarkedOpen(t, alice, bob, fundingOutPoint) + + // After the funding transaction was mined, Bob should have successfully + // sent the fundingLocked message, while Alice failed sending it. In + // Alice's case this means that there should be no messages for Bob, and + // the channel should still be in state 'markedOpen' select { - case <-alice.arbiterChan: - case <-time.After(time.Second * 5): - t.Fatalf("alice did not send channel to breach arbiter") + case msg := <-alice.msgChan: + t.Fatalf("did not expect any message from Alice: %v", msg) + default: + // Expected. + } + + // Bob will send funding locked to Alice + fundingLockedBob := checkNodeSendingFundingLocked(t, bob) + + // Sleep to make sure database write is finished. + time.Sleep(1 * time.Second) + + // Alice should still be markedOpen + state, _, err := alice.fundingMgr.getChannelOpeningState(fundingOutPoint) + if err != nil { + t.Fatalf("unable to get channel state: %v", err) + } + + if state != markedOpen { + t.Fatalf("expected state to be markedOpen, was %v", state) + } + + // While Bob successfully sent fundingLocked. + state, _, err = bob.fundingMgr.getChannelOpeningState(fundingOutPoint) + if err != nil { + t.Fatalf("unable to get channel state: %v", err) + } + + if state != fundingLockedSent { + t.Fatalf("expected state to be fundingLockedSent, was %v", state) + } + + // Alice should be waiting for the server to notify when Bob somes back online. + var peer *btcec.PublicKey + var con chan<- struct{} + select { + case peer = <-peerChan: + // Expected + case <-time.After(time.Second * 3): + t.Fatalf("alice did not register peer with server") } select { - case <-bob.arbiterChan: - case <-time.After(time.Second * 5): - t.Fatalf("bob did not send channel to breach arbiter") + case con = <-conChan: + // Expected + case <-time.After(time.Second * 3): + t.Fatalf("alice did not register connectedChan with server") } - // And send the new channel state to their peer. - select { - case c := <-alice.peer.newChannels: - close(c.done) - case <-time.After(time.Second * 5): - t.Fatalf("alice did not send new channel to peer") + if !peer.IsEqual(bobPubKey) { + t.Fatalf("expected to receive Bob's pubkey (%v), instead got %v", + bobPubKey, peer) } - select { - case c := <-bob.peer.newChannels: - close(c.done) - case <-time.After(time.Second * 5): - t.Fatalf("bob did not send new channel to peer") + // Fix Alice's SendToPeer, and notify that Bob is back online. + alice.fundingMgr.cfg.SendToPeer = func(target *btcec.PublicKey, + msgs ...lnwire.Message) error { + select { + case alice.msgChan <- msgs[0]: + case <-alice.shutdownChannel: + return fmt.Errorf("shutting down") + } + return nil } + close(con) + + // This should make Alice send the fundingLocked. + fundingLockedAlice := checkNodeSendingFundingLocked(t, alice) + + // Sleep to make sure database write is finished. + time.Sleep(500 * time.Millisecond) + + // The state should now be fundingLockedSent + state, _, err = alice.fundingMgr.getChannelOpeningState(fundingOutPoint) + if err != nil { + t.Fatalf("unable to get channel state: %v", err) + } + + if state != fundingLockedSent { + t.Fatalf("expected state to be fundingLockedSent, was %v", state) + } + + // Make sure both fundingManagers send the expected channel announcements. + assertChannelAnnouncements(t, alice, bob) + + // The funding process is now finished, wait for the + // OpenStatusUpdate_ChanOpen update + waitForOpenUpdate(t, updateChan) + + // The internal state-machine should now have deleted the channelStates + // from the database, as the channel is announced. + time.Sleep(300 * time.Millisecond) + assertNoChannelState(t, alice, bob, fundingOutPoint) + + // Exchange the fundingLocked messages. + alice.fundingMgr.processFundingLocked(fundingLockedBob, bobAddr) + bob.fundingMgr.processFundingLocked(fundingLockedAlice, aliceAddr) + + // Check that they notify the breach arbiter and peer about the new + // channel. + assertHandleFundingLocked(t, alice, bob) } @@ -1189,219 +1161,41 @@ func TestFundingManagerReceiveFundingLockedTwice(t *testing.T) { // The funding transaction was mined, so assert that both funding // managers now have the state of this channel 'markedOpen' in their // internal state machine. - state, _, err := alice.fundingMgr.getChannelOpeningState(fundingOutPoint) - if err != nil { - t.Fatalf("unable to get channel state: %v", err) - } - - if state != markedOpen { - t.Fatalf("expected state to be markedOpen, was %v", state) - } - state, _, err = bob.fundingMgr.getChannelOpeningState(fundingOutPoint) - if err != nil { - t.Fatalf("unable to get channel state: %v", err) - } - - if state != markedOpen { - t.Fatalf("expected state to be markedOpen, was %v", state) - } + assertMarkedOpen(t, alice, bob, fundingOutPoint) // After the funding transaction is mined, Alice will send // fundingLocked to Bob. - var aliceMsg lnwire.Message - select { - case aliceMsg = <-alice.msgChan: - case <-time.After(time.Second * 5): - t.Fatalf("alice did not send fundingLocked") - } - - _, ok := aliceMsg.(*lnwire.FundingLocked) - if !ok { - errorMsg, gotError := aliceMsg.(*lnwire.Error) - if gotError { - t.Fatalf("expected FundingLocked to be sent "+ - "from alice, instead got error: %v", - lnwire.ErrorCode(errorMsg.Data[0])) - } - t.Fatalf("expected FundingLocked to be sent from alice, "+ - "instead got %T", aliceMsg) - } + fundingLockedAlice := checkNodeSendingFundingLocked(t, alice) // And similarly Bob will send funding locked to Alice. - var bobMsg lnwire.Message - select { - case bobMsg = <-bob.msgChan: - case <-time.After(time.Second * 5): - t.Fatalf("bob did not send fundingLocked") - } - - fundingLockedBob, ok := bobMsg.(*lnwire.FundingLocked) - if !ok { - errorMsg, gotError := bobMsg.(*lnwire.Error) - if gotError { - t.Fatalf("expected FundingLocked to be sent "+ - "from bob, instead got error: %v", - lnwire.ErrorCode(errorMsg.Data[0])) - } - t.Fatalf("expected FundingLocked to be sent from bob, "+ - "instead got %T", bobMsg) - } + fundingLockedBob := checkNodeSendingFundingLocked(t, bob) // Sleep to make sure database write is finished. time.Sleep(300 * time.Millisecond) // Check that the state machine is updated accordingly - state, _, err = alice.fundingMgr.getChannelOpeningState(fundingOutPoint) - if err != nil { - t.Fatalf("unable to get channel state: %v", err) - } + assertFundingLockedSent(t, alice, bob, fundingOutPoint) - if state != fundingLockedSent { - t.Fatalf("expected state to be fundingLockedSent, was %v", state) - } - state, _, err = bob.fundingMgr.getChannelOpeningState(fundingOutPoint) - if err != nil { - t.Fatalf("unable to get channel state: %v", err) - } - - if state != fundingLockedSent { - t.Fatalf("expected state to be fundingLockedSent, was %v", state) - } - - // After the FundingLocked message is sent, the channel will be announced. - // A chanAnnouncement consists of three distinct messages: - // 1) ChannelAnnouncement - // 2) ChannelUpdate - // 3) AnnounceSignatures - // that will be announced in no particular order. - // A node announcement will also be sent. - announcements := make([]lnwire.Message, 4) - for i := 0; i < len(announcements); i++ { - select { - case announcements[i] = <-alice.announceChan: - case <-time.After(time.Second * 5): - t.Fatalf("alice did not send announcement %v", i) - } - } - - gotChannelAnnouncement := false - gotChannelUpdate := false - gotAnnounceSignatures := false - gotNodeAnnouncement := false - - for _, msg := range announcements { - switch msg.(type) { - case *lnwire.ChannelAnnouncement: - gotChannelAnnouncement = true - case *lnwire.ChannelUpdate: - gotChannelUpdate = true - case *lnwire.AnnounceSignatures: - gotAnnounceSignatures = true - case *lnwire.NodeAnnouncement: - gotNodeAnnouncement = true - } - } - - if !gotChannelAnnouncement { - t.Fatalf("did not get ChannelAnnouncement from Alice") - } - if !gotChannelUpdate { - t.Fatalf("did not get ChannelUpdate from Alice") - } - if !gotAnnounceSignatures { - t.Fatalf("did not get AnnounceSignatures from Alice") - } - if !gotNodeAnnouncement { - t.Fatalf("did not get NodeAnnouncement from Alice") - } - - // Do the check for Bob as well. - for i := 0; i < len(announcements); i++ { - select { - case announcements[i] = <-bob.announceChan: - case <-time.After(time.Second * 5): - t.Fatalf("bob did not send announcement %v", i) - } - } - - gotChannelAnnouncement = false - gotChannelUpdate = false - gotAnnounceSignatures = false - gotNodeAnnouncement = false - - for _, msg := range announcements { - switch msg.(type) { - case *lnwire.ChannelAnnouncement: - gotChannelAnnouncement = true - case *lnwire.ChannelUpdate: - gotChannelUpdate = true - case *lnwire.AnnounceSignatures: - gotAnnounceSignatures = true - case *lnwire.NodeAnnouncement: - gotNodeAnnouncement = true - } - } - - if !gotChannelAnnouncement { - t.Fatalf("did not get ChannelAnnouncement from Bob") - } - if !gotChannelUpdate { - t.Fatalf("did not get ChannelUpdate from Bob") - } - if !gotAnnounceSignatures { - t.Fatalf("did not get AnnounceSignatures from Bob") - } - if !gotNodeAnnouncement { - t.Fatalf("did not get NodeAnnouncement from Bob") - } + // Make sure both fundingManagers send the expected channel announcements. + assertChannelAnnouncements(t, alice, bob) // The funding process is now finished, wait for the // OpenStatusUpdate_ChanOpen update - var openUpdate *lnrpc.OpenStatusUpdate - select { - case openUpdate = <-updateChan: - case <-time.After(time.Second * 5): - t.Fatalf("alice did not send OpenStatusUpdate") - } - - _, ok = openUpdate.Update.(*lnrpc.OpenStatusUpdate_ChanOpen) - if !ok { - t.Fatal("OpenStatusUpdate was not OpenStatusUpdate_ChanOpen") - } + waitForOpenUpdate(t, updateChan) // The internal state-machine should now have deleted the channelStates // from the database, as the channel is announced. - state, _, err = alice.fundingMgr.getChannelOpeningState(fundingOutPoint) - if err != ErrChannelNotFound { - t.Fatalf("expected to not find channel state, but got: %v", state) - } - - // Need to give bob time to update database. time.Sleep(300 * time.Millisecond) + assertNoChannelState(t, alice, bob, fundingOutPoint) - state, _, err = bob.fundingMgr.getChannelOpeningState(fundingOutPoint) - if err != ErrChannelNotFound { - t.Fatalf("expected to not find channel state, but got: %v", state) - } - - // Send the fundingLocked message twice to Alice. + // Send the fundingLocked message twice to Alice, and once to Bob. alice.fundingMgr.processFundingLocked(fundingLockedBob, bobAddr) alice.fundingMgr.processFundingLocked(fundingLockedBob, bobAddr) + bob.fundingMgr.processFundingLocked(fundingLockedAlice, aliceAddr) - // Alice should send the new channel to the breach arbiter. - select { - case <-alice.arbiterChan: - case <-time.After(time.Millisecond * 300): - t.Fatalf("alice did not send channel to breach arbiter") - } - - // And send the new channel state to their peer. - select { - case c := <-alice.peer.newChannels: - close(c.done) - case <-time.After(time.Millisecond * 300): - t.Fatalf("alice did not send new channel to peer") - } + // Check that they notify the breach arbiter and peer about the new + // channel. + assertHandleFundingLocked(t, alice, bob) // Alice should not send the channel state the second time, as the // second funding locked should just be ignored. @@ -1463,200 +1257,32 @@ func TestFundingManagerRestartAfterChanAnn(t *testing.T) { // The funding transaction was mined, so assert that both funding // managers now have the state of this channel 'markedOpen' in their // internal state machine. - state, _, err := alice.fundingMgr.getChannelOpeningState(fundingOutPoint) - if err != nil { - t.Fatalf("unable to get channel state: %v", err) - } - - if state != markedOpen { - t.Fatalf("expected state to be markedOpen, was %v", state) - } - state, _, err = bob.fundingMgr.getChannelOpeningState(fundingOutPoint) - if err != nil { - t.Fatalf("unable to get channel state: %v", err) - } - - if state != markedOpen { - t.Fatalf("expected state to be markedOpen, was %v", state) - } + assertMarkedOpen(t, alice, bob, fundingOutPoint) // After the funding transaction is mined, Alice will send // fundingLocked to Bob. - var aliceMsg lnwire.Message - select { - case aliceMsg = <-alice.msgChan: - case <-time.After(time.Second * 5): - t.Fatalf("alice did not send fundingLocked") - } - - fundingLockedAlice, ok := aliceMsg.(*lnwire.FundingLocked) - if !ok { - errorMsg, gotError := aliceMsg.(*lnwire.Error) - if gotError { - t.Fatalf("expected FundingLocked to be sent "+ - "from alice, instead got error: %v", - lnwire.ErrorCode(errorMsg.Data[0])) - } - t.Fatalf("expected FundingLocked to be sent from alice, "+ - "instead got %T", aliceMsg) - } + fundingLockedAlice := checkNodeSendingFundingLocked(t, alice) // And similarly Bob will send funding locked to Alice. - var bobMsg lnwire.Message - select { - case bobMsg = <-bob.msgChan: - case <-time.After(time.Second * 5): - t.Fatalf("bob did not send fundingLocked") - } - - fundingLockedBob, ok := bobMsg.(*lnwire.FundingLocked) - if !ok { - errorMsg, gotError := bobMsg.(*lnwire.Error) - if gotError { - t.Fatalf("expected FundingLocked to be sent "+ - "from bob, instead got error: %v", - lnwire.ErrorCode(errorMsg.Data[0])) - } - t.Fatalf("expected FundingLocked to be sent from bob, "+ - "instead got %T", bobMsg) - } + fundingLockedBob := checkNodeSendingFundingLocked(t, bob) // Sleep to make sure database write is finished. time.Sleep(300 * time.Millisecond) // Check that the state machine is updated accordingly - state, _, err = alice.fundingMgr.getChannelOpeningState(fundingOutPoint) - if err != nil { - t.Fatalf("unable to get channel state: %v", err) - } + assertFundingLockedSent(t, alice, bob, fundingOutPoint) - if state != fundingLockedSent { - t.Fatalf("expected state to be fundingLockedSent, was %v", state) - } - state, _, err = bob.fundingMgr.getChannelOpeningState(fundingOutPoint) - if err != nil { - t.Fatalf("unable to get channel state: %v", err) - } - - if state != fundingLockedSent { - t.Fatalf("expected state to be fundingLockedSent, was %v", state) - } - - // After the FundingLocked message is sent, the channel will be announced. - // A chanAnnouncement consists of three distinct messages: - // 1) ChannelAnnouncement - // 2) ChannelUpdate - // 3) AnnounceSignatures - // that will be announced in no particular order. - // A node announcement will also be sent. - announcements := make([]lnwire.Message, 4) - for i := 0; i < len(announcements); i++ { - select { - case announcements[i] = <-alice.announceChan: - case <-time.After(time.Second * 5): - t.Fatalf("alice did not send announcement %v", i) - } - } - - gotChannelAnnouncement := false - gotChannelUpdate := false - gotAnnounceSignatures := false - gotNodeAnnouncement := false - - for _, msg := range announcements { - switch msg.(type) { - case *lnwire.ChannelAnnouncement: - gotChannelAnnouncement = true - case *lnwire.ChannelUpdate: - gotChannelUpdate = true - case *lnwire.AnnounceSignatures: - gotAnnounceSignatures = true - case *lnwire.NodeAnnouncement: - gotNodeAnnouncement = true - } - } - - if !gotChannelAnnouncement { - t.Fatalf("did not get ChannelAnnouncement from Alice") - } - if !gotChannelUpdate { - t.Fatalf("did not get ChannelUpdate from Alice") - } - if !gotAnnounceSignatures { - t.Fatalf("did not get AnnounceSignatures from Alice") - } - if !gotNodeAnnouncement { - t.Fatalf("did not get NodeAnnouncement from Alice") - } - - // Do the check for Bob as well. - for i := 0; i < len(announcements); i++ { - select { - case announcements[i] = <-bob.announceChan: - case <-time.After(time.Second * 5): - t.Fatalf("bob did not send announcement %v", i) - } - } - - gotChannelAnnouncement = false - gotChannelUpdate = false - gotAnnounceSignatures = false - gotNodeAnnouncement = false - - for _, msg := range announcements { - switch msg.(type) { - case *lnwire.ChannelAnnouncement: - gotChannelAnnouncement = true - case *lnwire.ChannelUpdate: - gotChannelUpdate = true - case *lnwire.AnnounceSignatures: - gotAnnounceSignatures = true - case *lnwire.NodeAnnouncement: - gotNodeAnnouncement = true - } - } - - if !gotChannelAnnouncement { - t.Fatalf("did not get ChannelAnnouncement from Bob") - } - if !gotChannelUpdate { - t.Fatalf("did not get ChannelUpdate from Bob") - } - if !gotAnnounceSignatures { - t.Fatalf("did not get AnnounceSignatures from Bob") - } - if !gotNodeAnnouncement { - t.Fatalf("did not get NodeAnnouncement from Bob") - } + // Make sure both fundingManagers send the expected channel announcements. + assertChannelAnnouncements(t, alice, bob) // The funding process is now finished, wait for the // OpenStatusUpdate_ChanOpen update - var openUpdate *lnrpc.OpenStatusUpdate - select { - case openUpdate = <-updateChan: - case <-time.After(time.Second * 5): - t.Fatalf("alice did not send OpenStatusUpdate") - } - - _, ok = openUpdate.Update.(*lnrpc.OpenStatusUpdate_ChanOpen) - if !ok { - t.Fatal("OpenStatusUpdate was not OpenStatusUpdate_ChanOpen") - } + waitForOpenUpdate(t, updateChan) // The internal state-machine should now have deleted the channelStates // from the database, as the channel is announced. - state, _, err = alice.fundingMgr.getChannelOpeningState(fundingOutPoint) - if err != ErrChannelNotFound { - t.Fatalf("expected to not find channel state, but got: %v", state) - } - - // Need to give bob time to update database. time.Sleep(300 * time.Millisecond) - - state, _, err = bob.fundingMgr.getChannelOpeningState(fundingOutPoint) - if err != ErrChannelNotFound { - t.Fatalf("expected to not find channel state, but got: %v", state) - } + assertNoChannelState(t, alice, bob, fundingOutPoint) // At this point we restart Alice's fundingManager, before she receives // the fundingLocked message. After restart, she will receive it, and @@ -1668,34 +1294,9 @@ func TestFundingManagerRestartAfterChanAnn(t *testing.T) { alice.fundingMgr.processFundingLocked(fundingLockedBob, bobAddr) bob.fundingMgr.processFundingLocked(fundingLockedAlice, aliceAddr) - // They should both send the new channel to the breach arbiter. - select { - case <-alice.arbiterChan: - case <-time.After(time.Second * 5): - t.Fatalf("alice did not send channel to breach arbiter") - } - - select { - case <-bob.arbiterChan: - case <-time.After(time.Second * 5): - t.Fatalf("bob did not send channel to breach arbiter") - } - - // And send the new channel state to their peer. - select { - case c := <-alice.peer.newChannels: - close(c.done) - case <-time.After(time.Second * 5): - t.Fatalf("alice did not send new channel to peer") - } - - select { - case c := <-bob.peer.newChannels: - close(c.done) - case <-time.After(time.Second * 5): - t.Fatalf("bob did not send new channel to peer") - } - + // Check that they notify the breach arbiter and peer about the new + // channel. + assertHandleFundingLocked(t, alice, bob) } // TestFundingManagerRestartAfterReceivingFundingLocked checks that the @@ -1725,84 +1326,20 @@ func TestFundingManagerRestartAfterReceivingFundingLocked(t *testing.T) { // The funding transaction was mined, so assert that both funding // managers now have the state of this channel 'markedOpen' in their // internal state machine. - state, _, err := alice.fundingMgr.getChannelOpeningState(fundingOutPoint) - if err != nil { - t.Fatalf("unable to get channel state: %v", err) - } - - if state != markedOpen { - t.Fatalf("expected state to be markedOpen, was %v", state) - } - state, _, err = bob.fundingMgr.getChannelOpeningState(fundingOutPoint) - if err != nil { - t.Fatalf("unable to get channel state: %v", err) - } - - if state != markedOpen { - t.Fatalf("expected state to be markedOpen, was %v", state) - } + assertMarkedOpen(t, alice, bob, fundingOutPoint) // After the funding transaction is mined, Alice will send // fundingLocked to Bob. - var aliceMsg lnwire.Message - select { - case aliceMsg = <-alice.msgChan: - case <-time.After(time.Second * 5): - t.Fatalf("alice did not send fundingLocked") - } - - fundingLockedAlice, ok := aliceMsg.(*lnwire.FundingLocked) - if !ok { - errorMsg, gotError := aliceMsg.(*lnwire.Error) - if gotError { - t.Fatalf("expected FundingLocked to be sent "+ - "from alice, instead got error: %v", - lnwire.ErrorCode(errorMsg.Data[0])) - } - t.Fatalf("expected FundingLocked to be sent from alice, "+ - "instead got %T", aliceMsg) - } + fundingLockedAlice := checkNodeSendingFundingLocked(t, alice) // And similarly Bob will send funding locked to Alice. - var bobMsg lnwire.Message - select { - case bobMsg = <-bob.msgChan: - case <-time.After(time.Second * 5): - t.Fatalf("bob did not send fundingLocked") - } - - fundingLockedBob, ok := bobMsg.(*lnwire.FundingLocked) - if !ok { - errorMsg, gotError := bobMsg.(*lnwire.Error) - if gotError { - t.Fatalf("expected FundingLocked to be sent "+ - "from bob, instead got error: %v", - lnwire.ErrorCode(errorMsg.Data[0])) - } - t.Fatalf("expected FundingLocked to be sent from bob, "+ - "instead got %T", bobMsg) - } + fundingLockedBob := checkNodeSendingFundingLocked(t, bob) // Sleep to make sure database write is finished. time.Sleep(300 * time.Millisecond) // Check that the state machine is updated accordingly - state, _, err = alice.fundingMgr.getChannelOpeningState(fundingOutPoint) - if err != nil { - t.Fatalf("unable to get channel state: %v", err) - } - - if state != fundingLockedSent { - t.Fatalf("expected state to be fundingLockedSent, was %v", state) - } - state, _, err = bob.fundingMgr.getChannelOpeningState(fundingOutPoint) - if err != nil { - t.Fatalf("unable to get channel state: %v", err) - } - - if state != fundingLockedSent { - t.Fatalf("expected state to be fundingLockedSent, was %v", state) - } + assertFundingLockedSent(t, alice, bob, fundingOutPoint) // Let Alice immediately get the fundingLocked message. alice.fundingMgr.processFundingLocked(fundingLockedBob, bobAddr) @@ -1824,92 +1361,8 @@ func TestFundingManagerRestartAfterReceivingFundingLocked(t *testing.T) { // Simulate Bob resending the message when Alice is back up. alice.fundingMgr.processFundingLocked(fundingLockedBob, bobAddr) - // After the FundingLocked message is sent, the channel will be announced. - // A chanAnnouncement consists of three distinct messages: - // 1) ChannelAnnouncement - // 2) ChannelUpdate - // 3) AnnounceSignatures - // that will be announced in no particular order. - // A node announcement will also be sent. - announcements := make([]lnwire.Message, 4) - for i := 0; i < len(announcements); i++ { - select { - case announcements[i] = <-alice.announceChan: - case <-time.After(time.Second * 5): - t.Fatalf("alice did not send announcement %v", i) - } - } - - gotChannelAnnouncement := false - gotChannelUpdate := false - gotAnnounceSignatures := false - gotNodeAnnouncement := false - - for _, msg := range announcements { - switch msg.(type) { - case *lnwire.ChannelAnnouncement: - gotChannelAnnouncement = true - case *lnwire.ChannelUpdate: - gotChannelUpdate = true - case *lnwire.AnnounceSignatures: - gotAnnounceSignatures = true - case *lnwire.NodeAnnouncement: - gotNodeAnnouncement = true - } - } - - if !gotChannelAnnouncement { - t.Fatalf("did not get ChannelAnnouncement from Alice") - } - if !gotChannelUpdate { - t.Fatalf("did not get ChannelUpdate from Alice") - } - if !gotAnnounceSignatures { - t.Fatalf("did not get AnnounceSignatures from Alice") - } - if !gotNodeAnnouncement { - t.Fatalf("did not get NodeAnnouncement from Alice") - } - - // Do the check for Bob as well. - for i := 0; i < len(announcements); i++ { - select { - case announcements[i] = <-bob.announceChan: - case <-time.After(time.Second * 5): - t.Fatalf("bob did not send announcement %v", i) - } - } - - gotChannelAnnouncement = false - gotChannelUpdate = false - gotAnnounceSignatures = false - gotNodeAnnouncement = false - - for _, msg := range announcements { - switch msg.(type) { - case *lnwire.ChannelAnnouncement: - gotChannelAnnouncement = true - case *lnwire.ChannelUpdate: - gotChannelUpdate = true - case *lnwire.AnnounceSignatures: - gotAnnounceSignatures = true - case *lnwire.NodeAnnouncement: - gotNodeAnnouncement = true - } - } - - if !gotChannelAnnouncement { - t.Fatalf("did not get ChannelAnnouncement from Bob") - } - if !gotChannelUpdate { - t.Fatalf("did not get ChannelUpdate from Bob") - } - if !gotAnnounceSignatures { - t.Fatalf("did not get AnnounceSignatures from Bob") - } - if !gotNodeAnnouncement { - t.Fatalf("did not get NodeAnnouncement from Bob") - } + // Make sure both fundingManagers send the expected channel announcements. + assertChannelAnnouncements(t, alice, bob) // The funding process is now finished. Since we recreated the // fundingManager, we don't have an update channel to synchronize on, @@ -1918,48 +1371,12 @@ func TestFundingManagerRestartAfterReceivingFundingLocked(t *testing.T) { // The internal state-machine should now have deleted the channelStates // from the database, as the channel is announced. - state, _, err = alice.fundingMgr.getChannelOpeningState(fundingOutPoint) - if err != ErrChannelNotFound { - t.Fatalf("expected to not find channel state, but got: %v", state) - } + assertNoChannelState(t, alice, bob, fundingOutPoint) - // Need to give bob time to update database. - time.Sleep(300 * time.Millisecond) - - state, _, err = bob.fundingMgr.getChannelOpeningState(fundingOutPoint) - if err != ErrChannelNotFound { - t.Fatalf("expected to not find channel state, but got: %v", state) - } - - // Exchange the fundingLocked messages. + // Also let Bob get the fundingLocked message. bob.fundingMgr.processFundingLocked(fundingLockedAlice, aliceAddr) - // They should both send the new channel to the breach arbiter. - select { - case <-alice.arbiterChan: - case <-time.After(time.Second * 5): - t.Fatalf("alice did not send channel to breach arbiter") - } - - select { - case <-bob.arbiterChan: - case <-time.After(time.Second * 5): - t.Fatalf("bob did not send channel to breach arbiter") - } - - // And send the new channel state to their peer. - select { - case c := <-alice.peer.newChannels: - close(c.done) - case <-time.After(time.Second * 5): - t.Fatalf("alice did not send new channel to peer") - } - - select { - case c := <-bob.peer.newChannels: - close(c.done) - case <-time.After(time.Second * 5): - t.Fatalf("bob did not send new channel to peer") - } - + // Check that they notify the breach arbiter and peer about the new + // channel. + assertHandleFundingLocked(t, alice, bob) }