fundingmanager test: add TestFundingManagerMaxPendingChannels
This commit is contained in:
parent
8b6e7b24aa
commit
b437d03174
@ -10,6 +10,7 @@ import (
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@ -447,11 +448,11 @@ func recreateAliceFundingManager(t *testing.T, alice *testNode) {
|
||||
}
|
||||
}
|
||||
|
||||
func setupFundingManagers(t *testing.T) (*testNode, *testNode) {
|
||||
func setupFundingManagers(t *testing.T, maxPendingChannels int) (*testNode, *testNode) {
|
||||
// We need to set the global config, as fundingManager uses
|
||||
// MaxPendingChannels, and it is usually set in lndMain().
|
||||
cfg = &config{
|
||||
MaxPendingChannels: defaultMaxPendingChannels,
|
||||
MaxPendingChannels: maxPendingChannels,
|
||||
}
|
||||
|
||||
aliceTestDir, err := ioutil.TempDir("", "alicelnwallet")
|
||||
@ -673,6 +674,8 @@ func assertFundingMsgSent(t *testing.T, msgChan chan lnwire.Message,
|
||||
sentMsg, ok = msg.(*lnwire.FundingSigned)
|
||||
case "FundingLocked":
|
||||
sentMsg, ok = msg.(*lnwire.FundingLocked)
|
||||
case "Error":
|
||||
sentMsg, ok = msg.(*lnwire.Error)
|
||||
default:
|
||||
t.Fatalf("unknown message type: %s", msgType)
|
||||
}
|
||||
@ -683,8 +686,10 @@ func assertFundingMsgSent(t *testing.T, msgChan chan lnwire.Message,
|
||||
t.Fatalf("expected %s to be sent, instead got error: %v",
|
||||
msgType, lnwire.ErrorCode(errorMsg.Data[0]))
|
||||
}
|
||||
t.Fatalf("expected %s to be sent, instead got %T",
|
||||
msgType, msg)
|
||||
|
||||
_, _, line, _ := runtime.Caller(1)
|
||||
t.Fatalf("expected %s to be sent, instead got %T at %v",
|
||||
msgType, msg, line)
|
||||
}
|
||||
|
||||
return sentMsg
|
||||
@ -950,7 +955,7 @@ func assertHandleFundingLocked(t *testing.T, alice, bob *testNode) {
|
||||
}
|
||||
|
||||
func TestFundingManagerNormalWorkflow(t *testing.T) {
|
||||
alice, bob := setupFundingManagers(t)
|
||||
alice, bob := setupFundingManagers(t, defaultMaxPendingChannels)
|
||||
defer tearDownFundingManagers(t, alice, bob)
|
||||
|
||||
// We will consume the channel updates as we go, so no buffering is needed.
|
||||
@ -1020,7 +1025,7 @@ func TestFundingManagerNormalWorkflow(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFundingManagerRestartBehavior(t *testing.T) {
|
||||
alice, bob := setupFundingManagers(t)
|
||||
alice, bob := setupFundingManagers(t, defaultMaxPendingChannels)
|
||||
defer tearDownFundingManagers(t, alice, bob)
|
||||
|
||||
// Run through the process of opening the channel, up until the funding
|
||||
@ -1151,7 +1156,7 @@ func TestFundingManagerRestartBehavior(t *testing.T) {
|
||||
// server to notify when the peer comes online, in case sending the
|
||||
// fundingLocked message fails the first time.
|
||||
func TestFundingManagerOfflinePeer(t *testing.T) {
|
||||
alice, bob := setupFundingManagers(t)
|
||||
alice, bob := setupFundingManagers(t, defaultMaxPendingChannels)
|
||||
defer tearDownFundingManagers(t, alice, bob)
|
||||
|
||||
// Run through the process of opening the channel, up until the funding
|
||||
@ -1282,7 +1287,7 @@ func TestFundingManagerOfflinePeer(t *testing.T) {
|
||||
// will properly clean up a zombie reservation that times out after the
|
||||
// initFundingMsg has been handled.
|
||||
func TestFundingManagerPeerTimeoutAfterInitFunding(t *testing.T) {
|
||||
alice, bob := setupFundingManagers(t)
|
||||
alice, bob := setupFundingManagers(t, defaultMaxPendingChannels)
|
||||
defer tearDownFundingManagers(t, alice, bob)
|
||||
|
||||
// We will consume the channel updates as we go, so no buffering is needed.
|
||||
@ -1342,7 +1347,7 @@ func TestFundingManagerPeerTimeoutAfterInitFunding(t *testing.T) {
|
||||
// will properly clean up a zombie reservation that times out after the
|
||||
// fundingOpenMsg has been handled.
|
||||
func TestFundingManagerPeerTimeoutAfterFundingOpen(t *testing.T) {
|
||||
alice, bob := setupFundingManagers(t)
|
||||
alice, bob := setupFundingManagers(t, defaultMaxPendingChannels)
|
||||
defer tearDownFundingManagers(t, alice, bob)
|
||||
|
||||
// We will consume the channel updates as we go, so no buffering is needed.
|
||||
@ -1411,7 +1416,7 @@ func TestFundingManagerPeerTimeoutAfterFundingOpen(t *testing.T) {
|
||||
// will properly clean up a zombie reservation that times out after the
|
||||
// fundingAcceptMsg has been handled.
|
||||
func TestFundingManagerPeerTimeoutAfterFundingAccept(t *testing.T) {
|
||||
alice, bob := setupFundingManagers(t)
|
||||
alice, bob := setupFundingManagers(t, defaultMaxPendingChannels)
|
||||
defer tearDownFundingManagers(t, alice, bob)
|
||||
|
||||
// We will consume the channel updates as we go, so no buffering is needed.
|
||||
@ -1485,7 +1490,7 @@ func TestFundingManagerPeerTimeoutAfterFundingAccept(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFundingManagerFundingTimeout(t *testing.T) {
|
||||
alice, bob := setupFundingManagers(t)
|
||||
alice, bob := setupFundingManagers(t, defaultMaxPendingChannels)
|
||||
defer tearDownFundingManagers(t, alice, bob)
|
||||
|
||||
// We will consume the channel updates as we go, so no buffering is needed.
|
||||
@ -1530,7 +1535,7 @@ func TestFundingManagerFundingTimeout(t *testing.T) {
|
||||
// the channel initiator, that it does not timeout when the lnd restarts.
|
||||
func TestFundingManagerFundingNotTimeoutInitiator(t *testing.T) {
|
||||
|
||||
alice, bob := setupFundingManagers(t)
|
||||
alice, bob := setupFundingManagers(t, defaultMaxPendingChannels)
|
||||
defer tearDownFundingManagers(t, alice, bob)
|
||||
|
||||
// We will consume the channel updates as we go, so no buffering is needed.
|
||||
@ -1597,7 +1602,7 @@ func TestFundingManagerFundingNotTimeoutInitiator(t *testing.T) {
|
||||
// continues to operate as expected in case we receive a duplicate fundingLocked
|
||||
// message.
|
||||
func TestFundingManagerReceiveFundingLockedTwice(t *testing.T) {
|
||||
alice, bob := setupFundingManagers(t)
|
||||
alice, bob := setupFundingManagers(t, defaultMaxPendingChannels)
|
||||
defer tearDownFundingManagers(t, alice, bob)
|
||||
|
||||
// We will consume the channel updates as we go, so no buffering is needed.
|
||||
@ -1686,7 +1691,7 @@ func TestFundingManagerReceiveFundingLockedTwice(t *testing.T) {
|
||||
// handles receiving a fundingLocked after the its own fundingLocked and channel
|
||||
// announcement is sent and gets restarted.
|
||||
func TestFundingManagerRestartAfterChanAnn(t *testing.T) {
|
||||
alice, bob := setupFundingManagers(t)
|
||||
alice, bob := setupFundingManagers(t, defaultMaxPendingChannels)
|
||||
defer tearDownFundingManagers(t, alice, bob)
|
||||
|
||||
// We will consume the channel updates as we go, so no buffering is needed.
|
||||
@ -1760,7 +1765,7 @@ func TestFundingManagerRestartAfterChanAnn(t *testing.T) {
|
||||
// fundingManager continues to operate as expected after it has received
|
||||
// fundingLocked and then gets restarted.
|
||||
func TestFundingManagerRestartAfterReceivingFundingLocked(t *testing.T) {
|
||||
alice, bob := setupFundingManagers(t)
|
||||
alice, bob := setupFundingManagers(t, defaultMaxPendingChannels)
|
||||
defer tearDownFundingManagers(t, alice, bob)
|
||||
|
||||
// We will consume the channel updates as we go, so no buffering is needed.
|
||||
@ -1830,7 +1835,7 @@ func TestFundingManagerRestartAfterReceivingFundingLocked(t *testing.T) {
|
||||
// (a channel not supposed to be announced to the rest of the network),
|
||||
// the announcementSignatures nor the nodeAnnouncement messages are sent.
|
||||
func TestFundingManagerPrivateChannel(t *testing.T) {
|
||||
alice, bob := setupFundingManagers(t)
|
||||
alice, bob := setupFundingManagers(t, defaultMaxPendingChannels)
|
||||
defer tearDownFundingManagers(t, alice, bob)
|
||||
|
||||
// We will consume the channel updates as we go, so no buffering is needed.
|
||||
@ -1910,7 +1915,7 @@ func TestFundingManagerPrivateChannel(t *testing.T) {
|
||||
// announcement signatures nor the node announcement messages are sent upon
|
||||
// restart.
|
||||
func TestFundingManagerPrivateRestart(t *testing.T) {
|
||||
alice, bob := setupFundingManagers(t)
|
||||
alice, bob := setupFundingManagers(t, defaultMaxPendingChannels)
|
||||
defer tearDownFundingManagers(t, alice, bob)
|
||||
|
||||
// We will consume the channel updates as we go, so no buffering is needed.
|
||||
@ -2000,7 +2005,7 @@ func TestFundingManagerPrivateRestart(t *testing.T) {
|
||||
// TestFundingManagerCustomChannelParameters checks that custom requirements we
|
||||
// specify during the channel funding flow is preserved correcly on both sides.
|
||||
func TestFundingManagerCustomChannelParameters(t *testing.T) {
|
||||
alice, bob := setupFundingManagers(t)
|
||||
alice, bob := setupFundingManagers(t, defaultMaxPendingChannels)
|
||||
defer tearDownFundingManagers(t, alice, bob)
|
||||
|
||||
// This is the custom parameters we'll use.
|
||||
@ -2195,3 +2200,164 @@ func TestFundingManagerCustomChannelParameters(t *testing.T) {
|
||||
t.Fatalf("alice did not publish funding tx")
|
||||
}
|
||||
}
|
||||
|
||||
// TestFundingManagerMaxPendingChannels checks that trying to open another
|
||||
// channel with the same peer when MaxPending channels are pending fails.
|
||||
func TestFundingManagerMaxPendingChannels(t *testing.T) {
|
||||
const maxPending = 4
|
||||
|
||||
alice, bob := setupFundingManagers(t, maxPending)
|
||||
defer tearDownFundingManagers(t, alice, bob)
|
||||
|
||||
// Create openChanReqs for maxPending+1 channels.
|
||||
var initReqs []*openChanReq
|
||||
for i := 0; i < maxPending+1; i++ {
|
||||
updateChan := make(chan *lnrpc.OpenStatusUpdate)
|
||||
errChan := make(chan error, 1)
|
||||
initReq := &openChanReq{
|
||||
targetPubkey: bob.privKey.PubKey(),
|
||||
chainHash: *activeNetParams.GenesisHash,
|
||||
localFundingAmt: 5000000,
|
||||
pushAmt: lnwire.NewMSatFromSatoshis(0),
|
||||
private: false,
|
||||
updates: updateChan,
|
||||
err: errChan,
|
||||
}
|
||||
initReqs = append(initReqs, initReq)
|
||||
}
|
||||
|
||||
// Kick of maxPending+1 funding workflows.
|
||||
var accepts []*lnwire.AcceptChannel
|
||||
var lastOpen *lnwire.OpenChannel
|
||||
for i, initReq := range initReqs {
|
||||
alice.fundingMgr.initFundingWorkflow(bob, initReq)
|
||||
|
||||
// Alice should have sent the OpenChannel message to Bob.
|
||||
var aliceMsg lnwire.Message
|
||||
select {
|
||||
case aliceMsg = <-alice.msgChan:
|
||||
case err := <-initReq.err:
|
||||
t.Fatalf("error init funding workflow: %v", err)
|
||||
case <-time.After(time.Second * 5):
|
||||
t.Fatalf("alice did not send OpenChannel message")
|
||||
}
|
||||
|
||||
openChannelReq, ok := aliceMsg.(*lnwire.OpenChannel)
|
||||
if !ok {
|
||||
errorMsg, gotError := aliceMsg.(*lnwire.Error)
|
||||
if gotError {
|
||||
t.Fatalf("expected OpenChannel to be sent "+
|
||||
"from bob, instead got error: %v",
|
||||
lnwire.ErrorCode(errorMsg.Data[0]))
|
||||
}
|
||||
t.Fatalf("expected OpenChannel to be sent from "+
|
||||
"alice, instead got %T", aliceMsg)
|
||||
}
|
||||
|
||||
// Let Bob handle the init message.
|
||||
bob.fundingMgr.processFundingOpen(openChannelReq, alice)
|
||||
|
||||
// Bob should answer with an AcceptChannel message for the
|
||||
// first maxPending channels.
|
||||
if i < maxPending {
|
||||
acceptChannelResponse := assertFundingMsgSent(
|
||||
t, bob.msgChan, "AcceptChannel",
|
||||
).(*lnwire.AcceptChannel)
|
||||
accepts = append(accepts, acceptChannelResponse)
|
||||
continue
|
||||
}
|
||||
|
||||
// For the last channel, Bob should answer with an error.
|
||||
lastOpen = openChannelReq
|
||||
_ = assertFundingMsgSent(
|
||||
t, bob.msgChan, "Error",
|
||||
).(*lnwire.Error)
|
||||
|
||||
}
|
||||
|
||||
// Forward the responses to Alice.
|
||||
var signs []*lnwire.FundingSigned
|
||||
for _, accept := range accepts {
|
||||
alice.fundingMgr.processFundingAccept(accept, bob)
|
||||
|
||||
// Alice responds with a FundingCreated message.
|
||||
fundingCreated := assertFundingMsgSent(
|
||||
t, alice.msgChan, "FundingCreated",
|
||||
).(*lnwire.FundingCreated)
|
||||
|
||||
// Give the message to Bob.
|
||||
bob.fundingMgr.processFundingCreated(fundingCreated, alice)
|
||||
|
||||
// Finally, Bob should send the FundingSigned message.
|
||||
fundingSigned := assertFundingMsgSent(
|
||||
t, bob.msgChan, "FundingSigned",
|
||||
).(*lnwire.FundingSigned)
|
||||
|
||||
signs = append(signs, fundingSigned)
|
||||
}
|
||||
|
||||
// Sending another init request from Alice should still make Bob
|
||||
// respond with an error.
|
||||
bob.fundingMgr.processFundingOpen(lastOpen, alice)
|
||||
_ = assertFundingMsgSent(
|
||||
t, bob.msgChan, "Error",
|
||||
).(*lnwire.Error)
|
||||
|
||||
// Give the FundingSigned messages to Alice.
|
||||
for i, sign := range signs {
|
||||
alice.fundingMgr.processFundingSigned(sign, bob)
|
||||
|
||||
// Alice should send a status update for each channel, and
|
||||
// publish a funding tx to the network.
|
||||
var pendingUpdate *lnrpc.OpenStatusUpdate
|
||||
select {
|
||||
case pendingUpdate = <-initReqs[i].updates:
|
||||
case <-time.After(time.Second * 5):
|
||||
t.Fatalf("alice did not send OpenStatusUpdate_ChanPending")
|
||||
}
|
||||
|
||||
_, ok := pendingUpdate.Update.(*lnrpc.OpenStatusUpdate_ChanPending)
|
||||
if !ok {
|
||||
t.Fatal("OpenStatusUpdate was not OpenStatusUpdate_ChanPending")
|
||||
}
|
||||
|
||||
select {
|
||||
case <-alice.publTxChan:
|
||||
case <-time.After(time.Second * 5):
|
||||
t.Fatalf("alice did not publish funding tx")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Sending another init request from Alice should still make Bob
|
||||
// respond with an error, since the funding transactions are not
|
||||
// confirmed yet,
|
||||
bob.fundingMgr.processFundingOpen(lastOpen, alice)
|
||||
_ = assertFundingMsgSent(
|
||||
t, bob.msgChan, "Error",
|
||||
).(*lnwire.Error)
|
||||
|
||||
// Notify that the transactions were mined.
|
||||
for i := 0; i < maxPending; i++ {
|
||||
alice.mockNotifier.oneConfChannel <- &chainntnfs.TxConfirmation{}
|
||||
bob.mockNotifier.oneConfChannel <- &chainntnfs.TxConfirmation{}
|
||||
|
||||
// Expect both to be sending FundingLocked.
|
||||
_ = assertFundingMsgSent(
|
||||
t, alice.msgChan, "FundingLocked",
|
||||
).(*lnwire.FundingLocked)
|
||||
|
||||
_ = assertFundingMsgSent(
|
||||
t, bob.msgChan, "FundingLocked",
|
||||
).(*lnwire.FundingLocked)
|
||||
|
||||
}
|
||||
|
||||
// Now opening another channel should work.
|
||||
bob.fundingMgr.processFundingOpen(lastOpen, alice)
|
||||
|
||||
// Bob should answer with an AcceptChannel message.
|
||||
_ = assertFundingMsgSent(
|
||||
t, bob.msgChan, "AcceptChannel",
|
||||
).(*lnwire.AcceptChannel)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user