From 389ecb535ba500693ebe4071545ef4dbe531efdc Mon Sep 17 00:00:00 2001 From: Ononiwu Maureen Date: Thu, 14 Mar 2024 14:45:27 +0100 Subject: [PATCH 1/5] peer: Change `createTestPeer` name. In this function `createTestPeer` is changed to `createTestPeerWithChannel`. This is useful in coming commits where we decouple the process of creating test peer from the function. Signed-off-by: Ononiwu Maureen --- peer/brontide_test.go | 36 +++++++++++++++++++----------------- peer/test_utils.go | 15 ++++++++------- 2 files changed, 27 insertions(+), 24 deletions(-) diff --git a/peer/brontide_test.go b/peer/brontide_test.go index 8ea8846b2..5772e9679 100644 --- a/peer/brontide_test.go +++ b/peer/brontide_test.go @@ -48,7 +48,7 @@ func TestPeerChannelClosureShutdownResponseLinkRemoved(t *testing.T) { mockSwitch := &mockMessageSwitch{} - alicePeer, bobChan, err := createTestPeer( + alicePeer, bobChan, err := createTestPeerWithChannel( t, notifier, broadcastTxChan, noUpdate, mockSwitch, ) require.NoError(t, err, "unable to create test channels") @@ -96,7 +96,7 @@ func TestPeerChannelClosureAcceptFeeResponder(t *testing.T) { mockSwitch := &mockMessageSwitch{} - alicePeer, bobChan, err := createTestPeer( + alicePeer, bobChan, err := createTestPeerWithChannel( t, notifier, broadcastTxChan, noUpdate, mockSwitch, ) require.NoError(t, err, "unable to create test channels") @@ -201,7 +201,7 @@ func TestPeerChannelClosureAcceptFeeInitiator(t *testing.T) { mockSwitch := &mockMessageSwitch{} - alicePeer, bobChan, err := createTestPeer( + alicePeer, bobChan, err := createTestPeerWithChannel( t, notifier, broadcastTxChan, noUpdate, mockSwitch, ) require.NoError(t, err, "unable to create test channels") @@ -325,7 +325,7 @@ func TestPeerChannelClosureFeeNegotiationsResponder(t *testing.T) { mockSwitch := &mockMessageSwitch{} - alicePeer, bobChan, err := createTestPeer( + alicePeer, bobChan, err := createTestPeerWithChannel( t, notifier, broadcastTxChan, noUpdate, mockSwitch, ) require.NoError(t, err, "unable to create test channels") @@ -512,7 +512,7 @@ func TestPeerChannelClosureFeeNegotiationsInitiator(t *testing.T) { mockSwitch := &mockMessageSwitch{} - alicePeer, bobChan, err := createTestPeer( + alicePeer, bobChan, err := createTestPeerWithChannel( t, notifier, broadcastTxChan, noUpdate, mockSwitch, ) require.NoError(t, err, "unable to create test channels") @@ -840,7 +840,7 @@ func TestCustomShutdownScript(t *testing.T) { mockSwitch := &mockMessageSwitch{} // Open a channel. - alicePeer, bobChan, err := createTestPeer( + alicePeer, bobChan, err := createTestPeerWithChannel( t, notifier, broadcastTxChan, test.update, mockSwitch, ) @@ -1195,7 +1195,7 @@ func TestUpdateNextRevocation(t *testing.T) { broadcastTxChan := make(chan *wire.MsgTx) mockSwitch := &mockMessageSwitch{} - alicePeer, bobChan, err := createTestPeer( + alicePeer, bobChan, err := createTestPeerWithChannel( t, notifier, broadcastTxChan, noUpdate, mockSwitch, ) require.NoError(err, "unable to create test channels") @@ -1412,7 +1412,7 @@ func TestHandleRemovePendingChannel(t *testing.T) { func TestStartupWriteMessageRace(t *testing.T) { t.Parallel() - // Set up parameters for createTestPeer. + // Set up parameters for createTestPeerWithChannel. notifier := &mock.ChainNotifier{ SpendChan: make(chan *chainntnfs.SpendDetail), EpochChan: make(chan *chainntnfs.BlockEpoch), @@ -1421,17 +1421,18 @@ func TestStartupWriteMessageRace(t *testing.T) { broadcastTxChan := make(chan *wire.MsgTx) mockSwitch := &mockMessageSwitch{} - // Use a callback to extract the channel created by createTestPeer, so - // we can mark it borked below. We can't mark it borked within the - // callback, since the channel hasn't been saved to the DB yet when the - // callback executes. + // Use a callback to extract the channel created by + // createTestPeerWithChannel, so we can mark it borked below. + // We can't mark it borked within the callback, since the channel hasn't + // been saved to the DB yet when the callback executes. var channel *channeldb.OpenChannel getChannels := func(a, b *channeldb.OpenChannel) { channel = a } - // createTestPeer creates a peer and a channel with that peer. - peer, _, err := createTestPeer( + // createTestPeerWithChannel creates a peer and a channel with that + // peer. + peer, _, err := createTestPeerWithChannel( t, notifier, broadcastTxChan, getChannels, mockSwitch, ) require.NoError(t, err, "unable to create test channel") @@ -1516,7 +1517,7 @@ func TestStartupWriteMessageRace(t *testing.T) { func TestRemovePendingChannel(t *testing.T) { t.Parallel() - // Set up parameters for createTestPeer. + // Set up parameters for createTestPeerWithChannel. notifier := &mock.ChainNotifier{ SpendChan: make(chan *chainntnfs.SpendDetail), EpochChan: make(chan *chainntnfs.BlockEpoch), @@ -1525,8 +1526,9 @@ func TestRemovePendingChannel(t *testing.T) { broadcastTxChan := make(chan *wire.MsgTx) mockSwitch := &mockMessageSwitch{} - // createTestPeer creates a peer and a channel with that peer. - peer, _, err := createTestPeer( + // createTestPeerWithChannel creates a peer and a channel with that + // peer. + peer, _, err := createTestPeerWithChannel( t, notifier, broadcastTxChan, noUpdate, mockSwitch, ) require.NoError(t, err, "unable to create test channel") diff --git a/peer/test_utils.go b/peer/test_utils.go index 05bfe6ad4..5080043a2 100644 --- a/peer/test_utils.go +++ b/peer/test_utils.go @@ -48,15 +48,16 @@ var ( testKeyLoc = keychain.KeyLocator{Family: keychain.KeyFamilyNodeKey} ) -// noUpdate is a function which can be used as a parameter in createTestPeer to -// call the setup code with no custom values on the channels set up. +// noUpdate is a function which can be used as a parameter in +// createTestPeerWithChannel to call the setup code with no custom values on +// the channels set up. var noUpdate = func(a, b *channeldb.OpenChannel) {} -// createTestPeer creates a channel between two nodes, and returns a peer for -// one of the nodes, together with the channel seen from both nodes. It takes -// an updateChan function which can be used to modify the default values on -// the channel states for each peer. -func createTestPeer(t *testing.T, notifier chainntnfs.ChainNotifier, +// createTestPeerWithChannel creates a channel between two nodes, and returns a +// peer for one of the nodes, together with the channel seen from both nodes. +// It takes an updateChan function which can be used to modify the default +// values on the channel states for each peer. +func createTestPeerWithChannel(t *testing.T, notifier chainntnfs.ChainNotifier, publTx chan *wire.MsgTx, updateChan func(a, b *channeldb.OpenChannel), mockSwitch *mockMessageSwitch) ( *Brontide, *lnwallet.LightningChannel, error) { From 536c69b7939991b7974c9dcdcf465ade7610019f Mon Sep 17 00:00:00 2001 From: Ononiwu Maureen Date: Thu, 14 Mar 2024 15:43:12 +0100 Subject: [PATCH 2/5] peer: `createTestPeerWithChannel` returns a struct The `createTestPeerWithChannel` function is made to return this newly created struct and error. This is useful because upcoming commits would require us returning more objects from the function. Signed-off-by: Ononiwu Maureen --- peer/brontide_test.go | 47 +++++++++++++++++++++++++++++++++---------- peer/test_utils.go | 46 +++++++++++++++++++++++++----------------- 2 files changed, 63 insertions(+), 30 deletions(-) diff --git a/peer/brontide_test.go b/peer/brontide_test.go index 5772e9679..270085674 100644 --- a/peer/brontide_test.go +++ b/peer/brontide_test.go @@ -48,11 +48,14 @@ func TestPeerChannelClosureShutdownResponseLinkRemoved(t *testing.T) { mockSwitch := &mockMessageSwitch{} - alicePeer, bobChan, err := createTestPeerWithChannel( + harness, err := createTestPeerWithChannel( t, notifier, broadcastTxChan, noUpdate, mockSwitch, ) require.NoError(t, err, "unable to create test channels") + alicePeer := harness.peer + bobChan := harness.channel + chanPoint := bobChan.ChannelPoint() chanID := lnwire.NewChanIDFromOutPoint(chanPoint) @@ -96,11 +99,14 @@ func TestPeerChannelClosureAcceptFeeResponder(t *testing.T) { mockSwitch := &mockMessageSwitch{} - alicePeer, bobChan, err := createTestPeerWithChannel( + harness, err := createTestPeerWithChannel( t, notifier, broadcastTxChan, noUpdate, mockSwitch, ) require.NoError(t, err, "unable to create test channels") + alicePeer := harness.peer + bobChan := harness.channel + chanPoint := bobChan.ChannelPoint() chanID := lnwire.NewChanIDFromOutPoint(chanPoint) @@ -201,11 +207,14 @@ func TestPeerChannelClosureAcceptFeeInitiator(t *testing.T) { mockSwitch := &mockMessageSwitch{} - alicePeer, bobChan, err := createTestPeerWithChannel( + harness, err := createTestPeerWithChannel( t, notifier, broadcastTxChan, noUpdate, mockSwitch, ) require.NoError(t, err, "unable to create test channels") + bobChan := harness.channel + alicePeer := harness.peer + chanPoint := bobChan.ChannelPoint() chanID := lnwire.NewChanIDFromOutPoint(chanPoint) mockLink := newMockUpdateHandler(chanID) @@ -325,11 +334,14 @@ func TestPeerChannelClosureFeeNegotiationsResponder(t *testing.T) { mockSwitch := &mockMessageSwitch{} - alicePeer, bobChan, err := createTestPeerWithChannel( + harness, err := createTestPeerWithChannel( t, notifier, broadcastTxChan, noUpdate, mockSwitch, ) require.NoError(t, err, "unable to create test channels") + bobChan := harness.channel + alicePeer := harness.peer + chanPoint := bobChan.ChannelPoint() chanID := lnwire.NewChanIDFromOutPoint(chanPoint) @@ -512,11 +524,14 @@ func TestPeerChannelClosureFeeNegotiationsInitiator(t *testing.T) { mockSwitch := &mockMessageSwitch{} - alicePeer, bobChan, err := createTestPeerWithChannel( + harness, err := createTestPeerWithChannel( t, notifier, broadcastTxChan, noUpdate, mockSwitch, ) require.NoError(t, err, "unable to create test channels") + alicePeer := harness.peer + bobChan := harness.channel + chanPoint := bobChan.ChannelPoint() chanID := lnwire.NewChanIDFromOutPoint(chanPoint) mockLink := newMockUpdateHandler(chanID) @@ -840,7 +855,7 @@ func TestCustomShutdownScript(t *testing.T) { mockSwitch := &mockMessageSwitch{} // Open a channel. - alicePeer, bobChan, err := createTestPeerWithChannel( + harness, err := createTestPeerWithChannel( t, notifier, broadcastTxChan, test.update, mockSwitch, ) @@ -848,13 +863,16 @@ func TestCustomShutdownScript(t *testing.T) { t.Fatalf("unable to create test channels: %v", err) } + alicePeer := harness.peer + bobChan := harness.channel + chanPoint := bobChan.ChannelPoint() chanID := lnwire.NewChanIDFromOutPoint(chanPoint) mockLink := newMockUpdateHandler(chanID) mockSwitch.links = append(mockSwitch.links, mockLink) - // Request initiator to cooperatively close the channel, with - // a specified delivery address. + // Request initiator to cooperatively close the channel, + // with a specified delivery address. updateChan := make(chan interface{}, 1) errChan := make(chan error, 1) closeCommand := htlcswitch.ChanClose{ @@ -1195,11 +1213,14 @@ func TestUpdateNextRevocation(t *testing.T) { broadcastTxChan := make(chan *wire.MsgTx) mockSwitch := &mockMessageSwitch{} - alicePeer, bobChan, err := createTestPeerWithChannel( + harness, err := createTestPeerWithChannel( t, notifier, broadcastTxChan, noUpdate, mockSwitch, ) require.NoError(err, "unable to create test channels") + bobChan := harness.channel + alicePeer := harness.peer + // testChannel is used to test the updateNextRevocation function. testChannel := bobChan.State() @@ -1432,11 +1453,13 @@ func TestStartupWriteMessageRace(t *testing.T) { // createTestPeerWithChannel creates a peer and a channel with that // peer. - peer, _, err := createTestPeerWithChannel( + harness, err := createTestPeerWithChannel( t, notifier, broadcastTxChan, getChannels, mockSwitch, ) require.NoError(t, err, "unable to create test channel") + peer := harness.peer + // Avoid the need to mock the channel graph by marking the channel // borked. Borked channels still get a reestablish message sent on // reconnect, while skipping channel graph checks and link creation. @@ -1528,11 +1551,13 @@ func TestRemovePendingChannel(t *testing.T) { // createTestPeerWithChannel creates a peer and a channel with that // peer. - peer, _, err := createTestPeerWithChannel( + harness, err := createTestPeerWithChannel( t, notifier, broadcastTxChan, noUpdate, mockSwitch, ) require.NoError(t, err, "unable to create test channel") + peer := harness.peer + // Add a pending channel to the peer Alice. errChan := make(chan error, 1) pendingChanID := lnwire.ChannelID{1} diff --git a/peer/test_utils.go b/peer/test_utils.go index 5080043a2..2f8f17bb7 100644 --- a/peer/test_utils.go +++ b/peer/test_utils.go @@ -53,6 +53,11 @@ var ( // the channels set up. var noUpdate = func(a, b *channeldb.OpenChannel) {} +type peerTestCtx struct { + peer *Brontide + channel *lnwallet.LightningChannel +} + // createTestPeerWithChannel creates a channel between two nodes, and returns a // peer for one of the nodes, together with the channel seen from both nodes. // It takes an updateChan function which can be used to modify the default @@ -60,7 +65,7 @@ var noUpdate = func(a, b *channeldb.OpenChannel) {} func createTestPeerWithChannel(t *testing.T, notifier chainntnfs.ChainNotifier, publTx chan *wire.MsgTx, updateChan func(a, b *channeldb.OpenChannel), mockSwitch *mockMessageSwitch) ( - *Brontide, *lnwallet.LightningChannel, error) { + *peerTestCtx, error) { nodeKeyLocator := keychain.KeyLocator{ Family: keychain.KeyFamilyNodeKey, @@ -142,23 +147,23 @@ func createTestPeerWithChannel(t *testing.T, notifier chainntnfs.ChainNotifier, bobRoot, err := chainhash.NewHash(bobKeyPriv.Serialize()) if err != nil { - return nil, nil, err + return nil, err } bobPreimageProducer := shachain.NewRevocationProducer(*bobRoot) bobFirstRevoke, err := bobPreimageProducer.AtIndex(0) if err != nil { - return nil, nil, err + return nil, err } bobCommitPoint := input.ComputeCommitmentPoint(bobFirstRevoke[:]) aliceRoot, err := chainhash.NewHash(aliceKeyPriv.Serialize()) if err != nil { - return nil, nil, err + return nil, err } alicePreimageProducer := shachain.NewRevocationProducer(*aliceRoot) aliceFirstRevoke, err := alicePreimageProducer.AtIndex(0) if err != nil { - return nil, nil, err + return nil, err } aliceCommitPoint := input.ComputeCommitmentPoint(aliceFirstRevoke[:]) @@ -168,12 +173,12 @@ func createTestPeerWithChannel(t *testing.T, notifier chainntnfs.ChainNotifier, isAliceInitiator, 0, ) if err != nil { - return nil, nil, err + return nil, err } dbAlice, err := channeldb.Open(t.TempDir()) if err != nil { - return nil, nil, err + return nil, err } t.Cleanup(func() { require.NoError(t, dbAlice.Close()) @@ -181,7 +186,7 @@ func createTestPeerWithChannel(t *testing.T, notifier chainntnfs.ChainNotifier, dbBob, err := channeldb.Open(t.TempDir()) if err != nil { - return nil, nil, err + return nil, err } t.Cleanup(func() { require.NoError(t, dbBob.Close()) @@ -190,7 +195,7 @@ func createTestPeerWithChannel(t *testing.T, notifier chainntnfs.ChainNotifier, estimator := chainfee.NewStaticEstimator(12500, 0) feePerKw, err := estimator.EstimateFeePerKW(1) if err != nil { - return nil, nil, err + return nil, err } // TODO(roasbeef): need to factor in commit fee? @@ -215,7 +220,7 @@ func createTestPeerWithChannel(t *testing.T, notifier chainntnfs.ChainNotifier, var chanIDBytes [8]byte if _, err := io.ReadFull(crand.Reader, chanIDBytes[:]); err != nil { - return nil, nil, err + return nil, err } shortChanID := lnwire.NewShortChanIDFromInt( @@ -266,7 +271,7 @@ func createTestPeerWithChannel(t *testing.T, notifier chainntnfs.ChainNotifier, } if err := aliceChannelState.SyncPending(aliceAddr, 0); err != nil { - return nil, nil, err + return nil, err } bobAddr := &net.TCPAddr{ @@ -275,7 +280,7 @@ func createTestPeerWithChannel(t *testing.T, notifier chainntnfs.ChainNotifier, } if err := bobChannelState.SyncPending(bobAddr, 0); err != nil { - return nil, nil, err + return nil, err } aliceSigner := input.NewMockSigner( @@ -290,7 +295,7 @@ func createTestPeerWithChannel(t *testing.T, notifier chainntnfs.ChainNotifier, aliceSigner, aliceChannelState, alicePool, ) if err != nil { - return nil, nil, err + return nil, err } _ = alicePool.Start() t.Cleanup(func() { @@ -302,7 +307,7 @@ func createTestPeerWithChannel(t *testing.T, notifier chainntnfs.ChainNotifier, bobSigner, bobChannelState, bobPool, ) if err != nil { - return nil, nil, err + return nil, err } _ = bobPool.Start() t.Cleanup(func() { @@ -346,15 +351,15 @@ func createTestPeerWithChannel(t *testing.T, notifier chainntnfs.ChainNotifier, }, }) if err != nil { - return nil, nil, err + return nil, err } if err = chanStatusMgr.Start(); err != nil { - return nil, nil, err + return nil, err } errBuffer, err := queue.NewCircularBuffer(ErrorBufferSize) if err != nil { - return nil, nil, err + return nil, err } var pubKey [33]byte @@ -381,7 +386,7 @@ func createTestPeerWithChannel(t *testing.T, notifier chainntnfs.ChainNotifier, }, ) if err != nil { - return nil, nil, err + return nil, err } // TODO(yy): change ChannelNotifier to be an interface. @@ -419,7 +424,10 @@ func createTestPeerWithChannel(t *testing.T, notifier chainntnfs.ChainNotifier, alicePeer.wg.Add(1) go alicePeer.channelManager() - return alicePeer, channelBob, nil + return &peerTestCtx{ + peer: alicePeer, + channel: channelBob, + }, nil } // mockMessageSwitch is a mock implementation of the messageSwitch interface From 8f76c5eeef1cddf9232e6a5f26df8bd558f0e513 Mon Sep 17 00:00:00 2001 From: Ononiwu Maureen Date: Fri, 15 Mar 2024 10:59:48 +0100 Subject: [PATCH 3/5] peer: Create mockswitch, publTx, notifier in .. test_utils Signed-off-by: Ononiwu Maureen --- peer/brontide_test.go | 133 ++++++++---------------------------------- peer/test_utils.go | 34 ++++++++--- 2 files changed, 48 insertions(+), 119 deletions(-) diff --git a/peer/brontide_test.go b/peer/brontide_test.go index 270085674..11a38e124 100644 --- a/peer/brontide_test.go +++ b/peer/brontide_test.go @@ -39,18 +39,7 @@ var ( func TestPeerChannelClosureShutdownResponseLinkRemoved(t *testing.T) { t.Parallel() - notifier := &mock.ChainNotifier{ - SpendChan: make(chan *chainntnfs.SpendDetail), - EpochChan: make(chan *chainntnfs.BlockEpoch), - ConfChan: make(chan *chainntnfs.TxConfirmation), - } - broadcastTxChan := make(chan *wire.MsgTx) - - mockSwitch := &mockMessageSwitch{} - - harness, err := createTestPeerWithChannel( - t, notifier, broadcastTxChan, noUpdate, mockSwitch, - ) + harness, err := createTestPeerWithChannel(t, noUpdate) require.NoError(t, err, "unable to create test channels") alicePeer := harness.peer @@ -90,22 +79,14 @@ func TestPeerChannelClosureShutdownResponseLinkRemoved(t *testing.T) { func TestPeerChannelClosureAcceptFeeResponder(t *testing.T) { t.Parallel() - notifier := &mock.ChainNotifier{ - SpendChan: make(chan *chainntnfs.SpendDetail), - EpochChan: make(chan *chainntnfs.BlockEpoch), - ConfChan: make(chan *chainntnfs.TxConfirmation), - } - broadcastTxChan := make(chan *wire.MsgTx) - - mockSwitch := &mockMessageSwitch{} - - harness, err := createTestPeerWithChannel( - t, notifier, broadcastTxChan, noUpdate, mockSwitch, - ) + harness, err := createTestPeerWithChannel(t, noUpdate) require.NoError(t, err, "unable to create test channels") alicePeer := harness.peer bobChan := harness.channel + mockSwitch := harness.mockSwitch + broadcastTxChan := harness.publishTx + notifier := harness.notifier chanPoint := bobChan.ChannelPoint() chanID := lnwire.NewChanIDFromOutPoint(chanPoint) @@ -198,22 +179,14 @@ func TestPeerChannelClosureAcceptFeeResponder(t *testing.T) { func TestPeerChannelClosureAcceptFeeInitiator(t *testing.T) { t.Parallel() - notifier := &mock.ChainNotifier{ - SpendChan: make(chan *chainntnfs.SpendDetail), - EpochChan: make(chan *chainntnfs.BlockEpoch), - ConfChan: make(chan *chainntnfs.TxConfirmation), - } - broadcastTxChan := make(chan *wire.MsgTx) - - mockSwitch := &mockMessageSwitch{} - - harness, err := createTestPeerWithChannel( - t, notifier, broadcastTxChan, noUpdate, mockSwitch, - ) + harness, err := createTestPeerWithChannel(t, noUpdate) require.NoError(t, err, "unable to create test channels") bobChan := harness.channel alicePeer := harness.peer + mockSwitch := harness.mockSwitch + broadcastTxChan := harness.publishTx + notifier := harness.notifier chanPoint := bobChan.ChannelPoint() chanID := lnwire.NewChanIDFromOutPoint(chanPoint) @@ -325,22 +298,14 @@ func TestPeerChannelClosureAcceptFeeInitiator(t *testing.T) { func TestPeerChannelClosureFeeNegotiationsResponder(t *testing.T) { t.Parallel() - notifier := &mock.ChainNotifier{ - SpendChan: make(chan *chainntnfs.SpendDetail), - EpochChan: make(chan *chainntnfs.BlockEpoch), - ConfChan: make(chan *chainntnfs.TxConfirmation), - } - broadcastTxChan := make(chan *wire.MsgTx) - - mockSwitch := &mockMessageSwitch{} - - harness, err := createTestPeerWithChannel( - t, notifier, broadcastTxChan, noUpdate, mockSwitch, - ) + harness, err := createTestPeerWithChannel(t, noUpdate) require.NoError(t, err, "unable to create test channels") bobChan := harness.channel alicePeer := harness.peer + mockSwitch := harness.mockSwitch + broadcastTxChan := harness.publishTx + notifier := harness.notifier chanPoint := bobChan.ChannelPoint() chanID := lnwire.NewChanIDFromOutPoint(chanPoint) @@ -515,22 +480,14 @@ func TestPeerChannelClosureFeeNegotiationsResponder(t *testing.T) { func TestPeerChannelClosureFeeNegotiationsInitiator(t *testing.T) { t.Parallel() - notifier := &mock.ChainNotifier{ - SpendChan: make(chan *chainntnfs.SpendDetail), - EpochChan: make(chan *chainntnfs.BlockEpoch), - ConfChan: make(chan *chainntnfs.TxConfirmation), - } - broadcastTxChan := make(chan *wire.MsgTx) - - mockSwitch := &mockMessageSwitch{} - - harness, err := createTestPeerWithChannel( - t, notifier, broadcastTxChan, noUpdate, mockSwitch, - ) + harness, err := createTestPeerWithChannel(t, noUpdate) require.NoError(t, err, "unable to create test channels") alicePeer := harness.peer bobChan := harness.channel + mockSwitch := harness.mockSwitch + broadcastTxChan := harness.publishTx + notifier := harness.notifier chanPoint := bobChan.ChannelPoint() chanID := lnwire.NewChanIDFromOutPoint(chanPoint) @@ -845,19 +802,9 @@ func TestCustomShutdownScript(t *testing.T) { test := test t.Run(test.name, func(t *testing.T) { - notifier := &mock.ChainNotifier{ - SpendChan: make(chan *chainntnfs.SpendDetail), - EpochChan: make(chan *chainntnfs.BlockEpoch), - ConfChan: make(chan *chainntnfs.TxConfirmation), - } - broadcastTxChan := make(chan *wire.MsgTx) - - mockSwitch := &mockMessageSwitch{} - // Open a channel. harness, err := createTestPeerWithChannel( - t, notifier, broadcastTxChan, test.update, - mockSwitch, + t, test.update, ) if err != nil { t.Fatalf("unable to create test channels: %v", err) @@ -865,6 +812,7 @@ func TestCustomShutdownScript(t *testing.T) { alicePeer := harness.peer bobChan := harness.channel + mockSwitch := harness.mockSwitch chanPoint := bobChan.ChannelPoint() chanID := lnwire.NewChanIDFromOutPoint(chanPoint) @@ -1203,19 +1151,7 @@ func TestUpdateNextRevocation(t *testing.T) { require := require.New(t) - // TODO(yy): create interface for lnwallet.LightningChannel so we can - // easily mock it without the following setups. - notifier := &mock.ChainNotifier{ - SpendChan: make(chan *chainntnfs.SpendDetail), - EpochChan: make(chan *chainntnfs.BlockEpoch), - ConfChan: make(chan *chainntnfs.TxConfirmation), - } - broadcastTxChan := make(chan *wire.MsgTx) - mockSwitch := &mockMessageSwitch{} - - harness, err := createTestPeerWithChannel( - t, notifier, broadcastTxChan, noUpdate, mockSwitch, - ) + harness, err := createTestPeerWithChannel(t, noUpdate) require.NoError(err, "unable to create test channels") bobChan := harness.channel @@ -1433,15 +1369,6 @@ func TestHandleRemovePendingChannel(t *testing.T) { func TestStartupWriteMessageRace(t *testing.T) { t.Parallel() - // Set up parameters for createTestPeerWithChannel. - notifier := &mock.ChainNotifier{ - SpendChan: make(chan *chainntnfs.SpendDetail), - EpochChan: make(chan *chainntnfs.BlockEpoch), - ConfChan: make(chan *chainntnfs.TxConfirmation), - } - broadcastTxChan := make(chan *wire.MsgTx) - mockSwitch := &mockMessageSwitch{} - // Use a callback to extract the channel created by // createTestPeerWithChannel, so we can mark it borked below. // We can't mark it borked within the callback, since the channel hasn't @@ -1453,9 +1380,7 @@ func TestStartupWriteMessageRace(t *testing.T) { // createTestPeerWithChannel creates a peer and a channel with that // peer. - harness, err := createTestPeerWithChannel( - t, notifier, broadcastTxChan, getChannels, mockSwitch, - ) + harness, err := createTestPeerWithChannel(t, getChannels) require.NoError(t, err, "unable to create test channel") peer := harness.peer @@ -1540,20 +1465,8 @@ func TestStartupWriteMessageRace(t *testing.T) { func TestRemovePendingChannel(t *testing.T) { t.Parallel() - // Set up parameters for createTestPeerWithChannel. - notifier := &mock.ChainNotifier{ - SpendChan: make(chan *chainntnfs.SpendDetail), - EpochChan: make(chan *chainntnfs.BlockEpoch), - ConfChan: make(chan *chainntnfs.TxConfirmation), - } - broadcastTxChan := make(chan *wire.MsgTx) - mockSwitch := &mockMessageSwitch{} - - // createTestPeerWithChannel creates a peer and a channel with that - // peer. - harness, err := createTestPeerWithChannel( - t, notifier, broadcastTxChan, noUpdate, mockSwitch, - ) + // createTestPeerWithChannel creates a peer and a channel. + harness, err := createTestPeerWithChannel(t, noUpdate) require.NoError(t, err, "unable to create test channel") peer := harness.peer diff --git a/peer/test_utils.go b/peer/test_utils.go index 2f8f17bb7..c872d0313 100644 --- a/peer/test_utils.go +++ b/peer/test_utils.go @@ -54,18 +54,31 @@ var ( var noUpdate = func(a, b *channeldb.OpenChannel) {} type peerTestCtx struct { - peer *Brontide - channel *lnwallet.LightningChannel + peer *Brontide + channel *lnwallet.LightningChannel + notifier *mock.ChainNotifier + publishTx <-chan *wire.MsgTx + mockSwitch *mockMessageSwitch } // createTestPeerWithChannel creates a channel between two nodes, and returns a // peer for one of the nodes, together with the channel seen from both nodes. // It takes an updateChan function which can be used to modify the default // values on the channel states for each peer. -func createTestPeerWithChannel(t *testing.T, notifier chainntnfs.ChainNotifier, - publTx chan *wire.MsgTx, updateChan func(a, b *channeldb.OpenChannel), - mockSwitch *mockMessageSwitch) ( - *peerTestCtx, error) { +func createTestPeerWithChannel(t *testing.T, updateChan func(a, + b *channeldb.OpenChannel)) (*peerTestCtx, error) { + + // TODO(yy): create interface for lnwallet.LightningChannel so we can + // easily mock it without the following setups. + notifier := &mock.ChainNotifier{ + SpendChan: make(chan *chainntnfs.SpendDetail), + EpochChan: make(chan *chainntnfs.BlockEpoch), + ConfChan: make(chan *chainntnfs.TxConfirmation), + } + + var mockSwitch *mockMessageSwitch + + publishTx := make(chan *wire.MsgTx) nodeKeyLocator := keychain.KeyLocator{ Family: keychain.KeyFamilyNodeKey, @@ -320,7 +333,7 @@ func createTestPeerWithChannel(t *testing.T, notifier chainntnfs.ChainNotifier, wallet := &lnwallet.LightningWallet{ WalletController: &mock.WalletController{ RootKey: aliceKeyPriv, - PublishedTransactions: publTx, + PublishedTransactions: publishTx, }, } @@ -425,8 +438,11 @@ func createTestPeerWithChannel(t *testing.T, notifier chainntnfs.ChainNotifier, go alicePeer.channelManager() return &peerTestCtx{ - peer: alicePeer, - channel: channelBob, + peer: alicePeer, + channel: channelBob, + notifier: notifier, + publishTx: publishTx, + mockSwitch: mockSwitch, }, nil } From 2ec0fe07173a2e41652d04e2f778e5ec3d6a7b83 Mon Sep 17 00:00:00 2001 From: Ononiwu Maureen Date: Fri, 15 Mar 2024 12:21:49 +0100 Subject: [PATCH 4/5] peer: Add new function to create test peer. Signed-off-by: Ononiwu Maureen --- peer/brontide_test.go | 199 +++++++---------------- peer/test_utils.go | 365 ++++++++++++++++++++++++++---------------- 2 files changed, 278 insertions(+), 286 deletions(-) diff --git a/peer/brontide_test.go b/peer/brontide_test.go index 11a38e124..3b0ae3ce2 100644 --- a/peer/brontide_test.go +++ b/peer/brontide_test.go @@ -6,22 +6,18 @@ import ( "testing" "time" - "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/channeldb" - "github.com/lightningnetwork/lnd/channelnotifier" "github.com/lightningnetwork/lnd/contractcourt" "github.com/lightningnetwork/lnd/htlcswitch" - "github.com/lightningnetwork/lnd/lntest/mock" "github.com/lightningnetwork/lnd/lntest/wait" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet/chancloser" "github.com/lightningnetwork/lnd/lnwire" - "github.com/lightningnetwork/lnd/pool" "github.com/stretchr/testify/require" ) @@ -42,8 +38,10 @@ func TestPeerChannelClosureShutdownResponseLinkRemoved(t *testing.T) { harness, err := createTestPeerWithChannel(t, noUpdate) require.NoError(t, err, "unable to create test channels") - alicePeer := harness.peer - bobChan := harness.channel + var ( + alicePeer = harness.peer + bobChan = harness.channel + ) chanPoint := bobChan.ChannelPoint() chanID := lnwire.NewChanIDFromOutPoint(chanPoint) @@ -82,11 +80,13 @@ func TestPeerChannelClosureAcceptFeeResponder(t *testing.T) { harness, err := createTestPeerWithChannel(t, noUpdate) require.NoError(t, err, "unable to create test channels") - alicePeer := harness.peer - bobChan := harness.channel - mockSwitch := harness.mockSwitch - broadcastTxChan := harness.publishTx - notifier := harness.notifier + var ( + alicePeer = harness.peer + bobChan = harness.channel + mockSwitch = harness.mockSwitch + broadcastTxChan = harness.publishTx + notifier = harness.notifier + ) chanPoint := bobChan.ChannelPoint() chanID := lnwire.NewChanIDFromOutPoint(chanPoint) @@ -182,11 +182,13 @@ func TestPeerChannelClosureAcceptFeeInitiator(t *testing.T) { harness, err := createTestPeerWithChannel(t, noUpdate) require.NoError(t, err, "unable to create test channels") - bobChan := harness.channel - alicePeer := harness.peer - mockSwitch := harness.mockSwitch - broadcastTxChan := harness.publishTx - notifier := harness.notifier + var ( + bobChan = harness.channel + alicePeer = harness.peer + mockSwitch = harness.mockSwitch + broadcastTxChan = harness.publishTx + notifier = harness.notifier + ) chanPoint := bobChan.ChannelPoint() chanID := lnwire.NewChanIDFromOutPoint(chanPoint) @@ -301,11 +303,13 @@ func TestPeerChannelClosureFeeNegotiationsResponder(t *testing.T) { harness, err := createTestPeerWithChannel(t, noUpdate) require.NoError(t, err, "unable to create test channels") - bobChan := harness.channel - alicePeer := harness.peer - mockSwitch := harness.mockSwitch - broadcastTxChan := harness.publishTx - notifier := harness.notifier + var ( + bobChan = harness.channel + alicePeer = harness.peer + mockSwitch = harness.mockSwitch + broadcastTxChan = harness.publishTx + notifier = harness.notifier + ) chanPoint := bobChan.ChannelPoint() chanID := lnwire.NewChanIDFromOutPoint(chanPoint) @@ -483,11 +487,13 @@ func TestPeerChannelClosureFeeNegotiationsInitiator(t *testing.T) { harness, err := createTestPeerWithChannel(t, noUpdate) require.NoError(t, err, "unable to create test channels") - alicePeer := harness.peer - bobChan := harness.channel - mockSwitch := harness.mockSwitch - broadcastTxChan := harness.publishTx - notifier := harness.notifier + var ( + alicePeer = harness.peer + bobChan = harness.channel + mockSwitch = harness.mockSwitch + broadcastTxChan = harness.publishTx + notifier = harness.notifier + ) chanPoint := bobChan.ChannelPoint() chanID := lnwire.NewChanIDFromOutPoint(chanPoint) @@ -810,9 +816,11 @@ func TestCustomShutdownScript(t *testing.T) { t.Fatalf("unable to create test channels: %v", err) } - alicePeer := harness.peer - bobChan := harness.channel - mockSwitch := harness.mockSwitch + var ( + alicePeer = harness.peer + bobChan = harness.channel + mockSwitch = harness.mockSwitch + ) chanPoint := bobChan.ChannelPoint() chanID := lnwire.NewChanIDFromOutPoint(chanPoint) @@ -966,35 +974,23 @@ func TestStaticRemoteDowngrade(t *testing.T) { test := test t.Run(test.name, func(t *testing.T) { - writeBufferPool := pool.NewWriteBuffer( - pool.DefaultWriteBufferGCInterval, - pool.DefaultWriteBufferExpiryInterval, + params := createTestPeer(t) + + var ( + p = params.peer + mockConn = params.mockConn + writePool = p.cfg.WritePool ) - - writePool := pool.NewWrite( - writeBufferPool, 1, timeout, - ) - require.NoError(t, writePool.Start()) - - mockConn := newMockConn(t, 1) - - p := Brontide{ - cfg: Config{ - LegacyFeatures: legacy, - Features: test.features, - Conn: mockConn, - WritePool: writePool, - PongBuf: make([]byte, lnwire.MaxPongBytes), - }, - log: peerLog, - } + // Set feature bits. + p.cfg.LegacyFeatures = legacy + p.cfg.Features = test.features var b bytes.Buffer _, err := lnwire.WriteMessage(&b, test.expectedInit, 0) require.NoError(t, err) - // Send our init message, assert that we write our expected message - // and shutdown our write pool. + // Send our init message, assert that we write our + // expected message and shutdown our write pool. require.NoError(t, p.sendInitMsg(test.legacy)) mockConn.assertWrite(b.Bytes()) require.NoError(t, writePool.Stop()) @@ -1022,78 +1018,15 @@ func genScript(t *testing.T, address string) lnwire.DeliveryAddress { func TestPeerCustomMessage(t *testing.T) { t.Parallel() - // Set up node Alice. - dbAlice, err := channeldb.Open(t.TempDir()) - require.NoError(t, err) + params := createTestPeer(t) - aliceKey, err := btcec.NewPrivateKey() - require.NoError(t, err) - - writeBufferPool := pool.NewWriteBuffer( - pool.DefaultWriteBufferGCInterval, - pool.DefaultWriteBufferExpiryInterval, + var ( + mockConn = params.mockConn + alicePeer = params.peer + receivedCustomChan = params.customChan ) - writePool := pool.NewWrite( - writeBufferPool, 1, timeout, - ) - require.NoError(t, writePool.Start()) - - readBufferPool := pool.NewReadBuffer( - pool.DefaultReadBufferGCInterval, - pool.DefaultReadBufferExpiryInterval, - ) - - readPool := pool.NewRead( - readBufferPool, 1, timeout, - ) - require.NoError(t, readPool.Start()) - - mockConn := newMockConn(t, 1) - - receivedCustomChan := make(chan *customMsg) - - remoteKey := [33]byte{8} - - notifier := &mock.ChainNotifier{ - SpendChan: make(chan *chainntnfs.SpendDetail), - EpochChan: make(chan *chainntnfs.BlockEpoch), - ConfChan: make(chan *chainntnfs.TxConfirmation), - } - - // TODO(yy): change ChannelNotifier to be an interface. - channelNotifier := channelnotifier.New(dbAlice.ChannelStateDB()) - require.NoError(t, channelNotifier.Start()) - t.Cleanup(func() { - require.NoError(t, channelNotifier.Stop(), - "stop channel notifier failed") - }) - - alicePeer := NewBrontide(Config{ - PubKeyBytes: remoteKey, - ChannelDB: dbAlice.ChannelStateDB(), - Addr: &lnwire.NetAddress{ - IdentityKey: aliceKey.PubKey(), - }, - PrunePersistentPeerConnection: func([33]byte) {}, - Features: lnwire.EmptyFeatureVector(), - LegacyFeatures: lnwire.EmptyFeatureVector(), - WritePool: writePool, - ReadPool: readPool, - Conn: mockConn, - ChainNotifier: notifier, - HandleCustomMessage: func( - peer [33]byte, msg *lnwire.Custom) error { - - receivedCustomChan <- &customMsg{ - peer: peer, - msg: *msg, - } - return nil - }, - PongBuf: make([]byte, lnwire.MaxPongBytes), - ChannelNotifier: channelNotifier, - }) + remoteKey := alicePeer.PubKey() // Set up the init sequence. go func() { @@ -1108,7 +1041,7 @@ func TestPeerCustomMessage(t *testing.T) { lnwire.NewRawFeatureVector(), ) var b bytes.Buffer - _, err = lnwire.WriteMessage(&b, initReplyMsg, 0) + _, err := lnwire.WriteMessage(&b, initReplyMsg, 0) require.NoError(t, err) mockConn.readMessages <- b.Bytes() @@ -1394,28 +1327,6 @@ func TestStartupWriteMessageRace(t *testing.T) { mockConn := newMockConn(t, 2) peer.cfg.Conn = mockConn - // Set up other configuration necessary to successfully execute - // peer.Start(). - peer.cfg.LegacyFeatures = lnwire.EmptyFeatureVector() - writeBufferPool := pool.NewWriteBuffer( - pool.DefaultWriteBufferGCInterval, - pool.DefaultWriteBufferExpiryInterval, - ) - writePool := pool.NewWrite( - writeBufferPool, 1, timeout, - ) - require.NoError(t, writePool.Start()) - peer.cfg.WritePool = writePool - readBufferPool := pool.NewReadBuffer( - pool.DefaultReadBufferGCInterval, - pool.DefaultReadBufferExpiryInterval, - ) - readPool := pool.NewRead( - readBufferPool, 1, timeout, - ) - require.NoError(t, readPool.Start()) - peer.cfg.ReadPool = readPool - // Send a message while starting the peer. As the peer starts up, it // should not trigger a data race between the sending of this message // and the sending of the channel reestablish message. diff --git a/peer/test_utils.go b/peer/test_utils.go index c872d0313..9a01e35ad 100644 --- a/peer/test_utils.go +++ b/peer/test_utils.go @@ -27,6 +27,7 @@ import ( "github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/netann" + "github.com/lightningnetwork/lnd/pool" "github.com/lightningnetwork/lnd/queue" "github.com/lightningnetwork/lnd/shachain" "github.com/stretchr/testify/require" @@ -54,11 +55,16 @@ var ( var noUpdate = func(a, b *channeldb.OpenChannel) {} type peerTestCtx struct { - peer *Brontide - channel *lnwallet.LightningChannel - notifier *mock.ChainNotifier - publishTx <-chan *wire.MsgTx - mockSwitch *mockMessageSwitch + peer *Brontide + channel *lnwallet.LightningChannel + notifier *mock.ChainNotifier + publishTx <-chan *wire.MsgTx + mockSwitch *mockMessageSwitch + db *channeldb.DB + privKey *btcec.PrivateKey + mockConn *mockMessageConn + customChan chan *customMsg + chanStatusMgr *netann.ChanStatusManager } // createTestPeerWithChannel creates a channel between two nodes, and returns a @@ -68,30 +74,26 @@ type peerTestCtx struct { func createTestPeerWithChannel(t *testing.T, updateChan func(a, b *channeldb.OpenChannel)) (*peerTestCtx, error) { - // TODO(yy): create interface for lnwallet.LightningChannel so we can - // easily mock it without the following setups. - notifier := &mock.ChainNotifier{ - SpendChan: make(chan *chainntnfs.SpendDetail), - EpochChan: make(chan *chainntnfs.BlockEpoch), - ConfChan: make(chan *chainntnfs.TxConfirmation), - } + params := createTestPeer(t) - var mockSwitch *mockMessageSwitch + var ( + publishTx = params.publishTx + mockSwitch = params.mockSwitch + alicePeer = params.peer + notifier = params.notifier + aliceKeyPriv = params.privKey + dbAlice = params.db + chanStatusMgr = params.chanStatusMgr + ) - publishTx := make(chan *wire.MsgTx) + err := chanStatusMgr.Start() + require.NoError(t, err) + t.Cleanup(func() { + require.NoError(t, chanStatusMgr.Stop()) + }) - nodeKeyLocator := keychain.KeyLocator{ - Family: keychain.KeyFamilyNodeKey, - } - aliceKeyPriv, aliceKeyPub := btcec.PrivKeyFromBytes( - channels.AlicesPrivKey, - ) - aliceKeySigner := keychain.NewPrivKeyMessageSigner( - aliceKeyPriv, nodeKeyLocator, - ) - bobKeyPriv, bobKeyPub := btcec.PrivKeyFromBytes( - channels.BobsPrivKey, - ) + aliceKeyPub := alicePeer.IdentityKey() + estimator := alicePeer.cfg.FeeEstimator channelCapacity := btcutil.Amount(10 * 1e8) channelBal := channelCapacity / 2 @@ -107,6 +109,10 @@ func createTestPeerWithChannel(t *testing.T, updateChan func(a, } fundingTxIn := wire.NewTxIn(prevOut, nil, nil) + bobKeyPriv, bobKeyPub := btcec.PrivKeyFromBytes( + channels.BobsPrivKey, + ) + aliceCfg := channeldb.ChannelConfig{ ChannelConstraints: channeldb.ChannelConstraints{ DustLimit: aliceDustLimit, @@ -189,14 +195,6 @@ func createTestPeerWithChannel(t *testing.T, updateChan func(a, return nil, err } - dbAlice, err := channeldb.Open(t.TempDir()) - if err != nil { - return nil, err - } - t.Cleanup(func() { - require.NoError(t, dbAlice.Close()) - }) - dbBob, err := channeldb.Open(t.TempDir()) if err != nil { return nil, err @@ -205,7 +203,6 @@ func createTestPeerWithChannel(t *testing.T, updateChan func(a, require.NoError(t, dbBob.Close()) }) - estimator := chainfee.NewStaticEstimator(12500, 0) feePerKw, err := estimator.EstimateFeePerKW(1) if err != nil { return nil, err @@ -278,11 +275,7 @@ func createTestPeerWithChannel(t *testing.T, updateChan func(a, // Set custom values on the channel states. updateChan(aliceChannelState, bobChannelState) - aliceAddr := &net.TCPAddr{ - IP: net.ParseIP("127.0.0.1"), - Port: 18555, - } - + aliceAddr := alicePeer.cfg.Addr.Address if err := aliceChannelState.SyncPending(aliceAddr, 0); err != nil { return nil, err } @@ -327,109 +320,9 @@ func createTestPeerWithChannel(t *testing.T, updateChan func(a, require.NoError(t, bobPool.Stop()) }) - chainIO := &mock.ChainIO{ - BestHeight: broadcastHeight, - } - wallet := &lnwallet.LightningWallet{ - WalletController: &mock.WalletController{ - RootKey: aliceKeyPriv, - PublishedTransactions: publishTx, - }, - } - - // If mockSwitch is not set by the caller, set it to the default as the - // caller does not need to control it. - if mockSwitch == nil { - mockSwitch = &mockMessageSwitch{} - } - - nodeSignerAlice := netann.NewNodeSigner(aliceKeySigner) - - const chanActiveTimeout = time.Minute - - chanStatusMgr, err := netann.NewChanStatusManager(&netann.ChanStatusConfig{ - ChanStatusSampleInterval: 30 * time.Second, - ChanEnableTimeout: chanActiveTimeout, - ChanDisableTimeout: 2 * time.Minute, - DB: dbAlice.ChannelStateDB(), - Graph: dbAlice.ChannelGraph(), - MessageSigner: nodeSignerAlice, - OurPubKey: aliceKeyPub, - OurKeyLoc: testKeyLoc, - IsChannelActive: func(lnwire.ChannelID) bool { return true }, - ApplyChannelUpdate: func(*lnwire.ChannelUpdate, - *wire.OutPoint, bool) error { - - return nil - }, - }) - if err != nil { - return nil, err - } - if err = chanStatusMgr.Start(); err != nil { - return nil, err - } - - errBuffer, err := queue.NewCircularBuffer(ErrorBufferSize) - if err != nil { - return nil, err - } - - var pubKey [33]byte - copy(pubKey[:], aliceKeyPub.SerializeCompressed()) - - cfgAddr := &lnwire.NetAddress{ - IdentityKey: aliceKeyPub, - Address: aliceAddr, - ChainNet: wire.SimNet, - } - - interceptableSwitchNotifier := &mock.ChainNotifier{ - EpochChan: make(chan *chainntnfs.BlockEpoch, 1), - } - interceptableSwitchNotifier.EpochChan <- &chainntnfs.BlockEpoch{ - Height: 1, - } - - interceptableSwitch, err := htlcswitch.NewInterceptableSwitch( - &htlcswitch.InterceptableSwitchConfig{ - CltvRejectDelta: testCltvRejectDelta, - CltvInterceptDelta: testCltvRejectDelta + 3, - Notifier: interceptableSwitchNotifier, - }, + alicePeer.remoteFeatures = lnwire.NewFeatureVector( + nil, lnwire.Features, ) - if err != nil { - return nil, err - } - - // TODO(yy): change ChannelNotifier to be an interface. - channelNotifier := channelnotifier.New(dbAlice.ChannelStateDB()) - require.NoError(t, channelNotifier.Start()) - t.Cleanup(func() { - require.NoError(t, channelNotifier.Stop(), - "stop channel notifier failed") - }) - - cfg := &Config{ - Addr: cfgAddr, - PubKeyBytes: pubKey, - ErrorBuffer: errBuffer, - ChainIO: chainIO, - Switch: mockSwitch, - ChanActiveTimeout: chanActiveTimeout, - InterceptSwitch: interceptableSwitch, - ChannelDB: dbAlice.ChannelStateDB(), - FeeEstimator: estimator, - Wallet: wallet, - ChainNotifier: notifier, - ChanStatusMgr: chanStatusMgr, - Features: lnwire.NewFeatureVector(nil, lnwire.Features), - DisconnectPeer: func(b *btcec.PublicKey) error { return nil }, - ChannelNotifier: channelNotifier, - } - - alicePeer := NewBrontide(*cfg) - alicePeer.remoteFeatures = lnwire.NewFeatureVector(nil, lnwire.Features) chanID := lnwire.NewChanIDFromOutPoint(channelAlice.ChannelPoint()) alicePeer.activeChannels.Store(chanID, channelAlice) @@ -643,3 +536,191 @@ func (m *mockMessageConn) LocalAddr() net.Addr { func (m *mockMessageConn) Close() error { return nil } + +// createTestPeer creates a new peer for testing and returns a context struct +// containing necessary handles and mock objects for conducting tests on peer +// functionalities. +func createTestPeer(t *testing.T) *peerTestCtx { + nodeKeyLocator := keychain.KeyLocator{ + Family: keychain.KeyFamilyNodeKey, + } + + aliceKeyPriv, aliceKeyPub := btcec.PrivKeyFromBytes( + channels.AlicesPrivKey, + ) + + aliceKeySigner := keychain.NewPrivKeyMessageSigner( + aliceKeyPriv, nodeKeyLocator, + ) + + aliceAddr := &net.TCPAddr{ + IP: net.ParseIP("127.0.0.1"), + Port: 18555, + } + cfgAddr := &lnwire.NetAddress{ + IdentityKey: aliceKeyPub, + Address: aliceAddr, + ChainNet: wire.SimNet, + } + + errBuffer, err := queue.NewCircularBuffer(ErrorBufferSize) + require.NoError(t, err) + + chainIO := &mock.ChainIO{ + BestHeight: broadcastHeight, + } + + publishTx := make(chan *wire.MsgTx) + wallet := &lnwallet.LightningWallet{ + WalletController: &mock.WalletController{ + RootKey: aliceKeyPriv, + PublishedTransactions: publishTx, + }, + } + + const chanActiveTimeout = time.Minute + + dbAlice, err := channeldb.Open(t.TempDir()) + require.NoError(t, err) + t.Cleanup(func() { + require.NoError(t, dbAlice.Close()) + }) + + nodeSignerAlice := netann.NewNodeSigner(aliceKeySigner) + + chanStatusMgr, err := netann.NewChanStatusManager(&netann. + ChanStatusConfig{ + ChanStatusSampleInterval: 30 * time.Second, + ChanEnableTimeout: chanActiveTimeout, + ChanDisableTimeout: 2 * time.Minute, + DB: dbAlice.ChannelStateDB(), + Graph: dbAlice.ChannelGraph(), + MessageSigner: nodeSignerAlice, + OurPubKey: aliceKeyPub, + OurKeyLoc: testKeyLoc, + IsChannelActive: func(lnwire.ChannelID) bool { + return true + }, + ApplyChannelUpdate: func(*lnwire.ChannelUpdate, + *wire.OutPoint, bool) error { + + return nil + }, + }) + require.NoError(t, err) + + interceptableSwitchNotifier := &mock.ChainNotifier{ + EpochChan: make(chan *chainntnfs.BlockEpoch, 1), + } + interceptableSwitchNotifier.EpochChan <- &chainntnfs.BlockEpoch{ + Height: 1, + } + + interceptableSwitch, err := htlcswitch.NewInterceptableSwitch( + &htlcswitch.InterceptableSwitchConfig{ + CltvRejectDelta: testCltvRejectDelta, + CltvInterceptDelta: testCltvRejectDelta + 3, + Notifier: interceptableSwitchNotifier, + }, + ) + require.NoError(t, err) + + // TODO(yy): create interface for lnwallet.LightningChannel so we can + // easily mock it without the following setups. + notifier := &mock.ChainNotifier{ + SpendChan: make(chan *chainntnfs.SpendDetail), + EpochChan: make(chan *chainntnfs.BlockEpoch), + ConfChan: make(chan *chainntnfs.TxConfirmation), + } + + mockSwitch := &mockMessageSwitch{} + + // TODO(yy): change ChannelNotifier to be an interface. + channelNotifier := channelnotifier.New(dbAlice.ChannelStateDB()) + require.NoError(t, channelNotifier.Start()) + t.Cleanup(func() { + require.NoError(t, channelNotifier.Stop(), + "stop channel notifier failed") + }) + + writeBufferPool := pool.NewWriteBuffer( + pool.DefaultWriteBufferGCInterval, + pool.DefaultWriteBufferExpiryInterval, + ) + + writePool := pool.NewWrite( + writeBufferPool, 1, timeout, + ) + require.NoError(t, writePool.Start()) + + readBufferPool := pool.NewReadBuffer( + pool.DefaultReadBufferGCInterval, + pool.DefaultReadBufferExpiryInterval, + ) + + readPool := pool.NewRead( + readBufferPool, 1, timeout, + ) + require.NoError(t, readPool.Start()) + + mockConn := newMockConn(t, 1) + + receivedCustomChan := make(chan *customMsg) + + var pubKey [33]byte + copy(pubKey[:], aliceKeyPub.SerializeCompressed()) + + estimator := chainfee.NewStaticEstimator(12500, 0) + + cfg := &Config{ + Addr: cfgAddr, + PubKeyBytes: pubKey, + ErrorBuffer: errBuffer, + ChainIO: chainIO, + Switch: mockSwitch, + ChanActiveTimeout: chanActiveTimeout, + InterceptSwitch: interceptableSwitch, + ChannelDB: dbAlice.ChannelStateDB(), + FeeEstimator: estimator, + Wallet: wallet, + ChainNotifier: notifier, + ChanStatusMgr: chanStatusMgr, + Features: lnwire.NewFeatureVector( + nil, lnwire.Features, + ), + DisconnectPeer: func(b *btcec.PublicKey) error { + return nil + }, + ChannelNotifier: channelNotifier, + PrunePersistentPeerConnection: func([33]byte) {}, + LegacyFeatures: lnwire.EmptyFeatureVector(), + WritePool: writePool, + ReadPool: readPool, + Conn: mockConn, + HandleCustomMessage: func( + peer [33]byte, msg *lnwire.Custom) error { + + receivedCustomChan <- &customMsg{ + peer: peer, + msg: *msg, + } + + return nil + }, + PongBuf: make([]byte, lnwire.MaxPongBytes), + } + + alicePeer := NewBrontide(*cfg) + + return &peerTestCtx{ + publishTx: publishTx, + mockSwitch: mockSwitch, + peer: alicePeer, + notifier: notifier, + db: dbAlice, + privKey: aliceKeyPriv, + mockConn: mockConn, + customChan: receivedCustomChan, + chanStatusMgr: chanStatusMgr, + } +} From b741132a81ab1412f005aefdc9467f31bf2e5754 Mon Sep 17 00:00:00 2001 From: Ononiwu Maureen Date: Fri, 15 Mar 2024 15:56:48 +0100 Subject: [PATCH 5/5] peer: Add `startPeer` test function Signed-off-by: Ononiwu Maureen --- peer/brontide_test.go | 56 ++++++++++--------------------------------- peer/test_utils.go | 50 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 44 deletions(-) diff --git a/peer/brontide_test.go b/peer/brontide_test.go index 3b0ae3ce2..d2f3fc7bc 100644 --- a/peer/brontide_test.go +++ b/peer/brontide_test.go @@ -13,6 +13,7 @@ import ( "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/contractcourt" + "github.com/lightningnetwork/lnd/fn" "github.com/lightningnetwork/lnd/htlcswitch" "github.com/lightningnetwork/lnd/lntest/wait" "github.com/lightningnetwork/lnd/lnwallet" @@ -1024,31 +1025,13 @@ func TestPeerCustomMessage(t *testing.T) { mockConn = params.mockConn alicePeer = params.peer receivedCustomChan = params.customChan + remoteKey = alicePeer.PubKey() ) - remoteKey := alicePeer.PubKey() - - // Set up the init sequence. - go func() { - // Read init message. - <-mockConn.writtenMessages - - // Write the init reply message. - initReplyMsg := lnwire.NewInitMessage( - lnwire.NewRawFeatureVector( - lnwire.DataLossProtectRequired, - ), - lnwire.NewRawFeatureVector(), - ) - var b bytes.Buffer - _, err := lnwire.WriteMessage(&b, initReplyMsg, 0) - require.NoError(t, err) - - mockConn.readMessages <- b.Bytes() - }() - - // Start the peer. - require.NoError(t, alicePeer.Start()) + // Start peer. + startPeerDone := startPeer(t, mockConn, alicePeer) + _, err := fn.RecvOrTimeout(startPeerDone, 2*timeout) + require.NoError(t, err) // Send a custom message. customMsg, err := lnwire.NewCustom( @@ -1330,33 +1313,18 @@ func TestStartupWriteMessageRace(t *testing.T) { // Send a message while starting the peer. As the peer starts up, it // should not trigger a data race between the sending of this message // and the sending of the channel reestablish message. - sendPingDone := make(chan struct{}) + var sendPingDone = make(chan struct{}) go func() { require.NoError(t, peer.SendMessage(true, lnwire.NewPing(0))) close(sendPingDone) }() - // Handle init messages. - go func() { - // Read init message. - <-mockConn.writtenMessages - - // Write the init reply message. - initReplyMsg := lnwire.NewInitMessage( - lnwire.NewRawFeatureVector( - lnwire.DataLossProtectRequired, - ), - lnwire.NewRawFeatureVector(), - ) - var b bytes.Buffer - _, err = lnwire.WriteMessage(&b, initReplyMsg, 0) - require.NoError(t, err) - - mockConn.readMessages <- b.Bytes() - }() - // Start the peer. No data race should occur. - require.NoError(t, peer.Start()) + startPeerDone := startPeer(t, mockConn, peer) + + // Ensure startup is complete. + _, err = fn.RecvOrTimeout(startPeerDone, 2*timeout) + require.NoError(t, err) // Ensure messages were sent during startup. <-sendPingDone diff --git a/peer/test_utils.go b/peer/test_utils.go index 9a01e35ad..8667b04cd 100644 --- a/peer/test_utils.go +++ b/peer/test_utils.go @@ -18,6 +18,7 @@ import ( "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/channelnotifier" + "github.com/lightningnetwork/lnd/fn" "github.com/lightningnetwork/lnd/htlcswitch" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/keychain" @@ -724,3 +725,52 @@ func createTestPeer(t *testing.T) *peerTestCtx { chanStatusMgr: chanStatusMgr, } } + +// startPeer invokes the `Start` method on the specified peer and handles any +// initial startup messages for testing. +func startPeer(t *testing.T, mockConn *mockMessageConn, + peer *Brontide) <-chan struct{} { + + // Start the peer in a goroutine so that we can handle and test for + // startup messages. Successfully sending and receiving init message, + // indicates a successful startup. + done := make(chan struct{}) + go func() { + require.NoError(t, peer.Start()) + close(done) + }() + + // Receive the init message that should be the first message received on + // startup. + rawMsg, err := fn.RecvOrTimeout[[]byte]( + mockConn.writtenMessages, timeout, + ) + require.NoError(t, err) + + msgReader := bytes.NewReader(rawMsg) + nextMsg, err := lnwire.ReadMessage(msgReader, 0) + require.NoError(t, err) + + _, ok := nextMsg.(*lnwire.Init) + require.True(t, ok) + + // Write the reply for the init message to complete the startup. + initReplyMsg := lnwire.NewInitMessage( + lnwire.NewRawFeatureVector( + lnwire.DataLossProtectRequired, + lnwire.GossipQueriesOptional, + ), + lnwire.NewRawFeatureVector(), + ) + + var b bytes.Buffer + _, err = lnwire.WriteMessage(&b, initReplyMsg, 0) + require.NoError(t, err) + + ok = fn.SendOrQuit[[]byte, struct{}]( + mockConn.readMessages, b.Bytes(), make(chan struct{}), + ) + require.True(t, ok) + + return done +}