fundingmanager test: add TestFundingManagerMaxPendingChannels
This commit is contained in:
parent
8b6e7b24aa
commit
b437d03174
@ -10,6 +10,7 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"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
|
// We need to set the global config, as fundingManager uses
|
||||||
// MaxPendingChannels, and it is usually set in lndMain().
|
// MaxPendingChannels, and it is usually set in lndMain().
|
||||||
cfg = &config{
|
cfg = &config{
|
||||||
MaxPendingChannels: defaultMaxPendingChannels,
|
MaxPendingChannels: maxPendingChannels,
|
||||||
}
|
}
|
||||||
|
|
||||||
aliceTestDir, err := ioutil.TempDir("", "alicelnwallet")
|
aliceTestDir, err := ioutil.TempDir("", "alicelnwallet")
|
||||||
@ -673,6 +674,8 @@ func assertFundingMsgSent(t *testing.T, msgChan chan lnwire.Message,
|
|||||||
sentMsg, ok = msg.(*lnwire.FundingSigned)
|
sentMsg, ok = msg.(*lnwire.FundingSigned)
|
||||||
case "FundingLocked":
|
case "FundingLocked":
|
||||||
sentMsg, ok = msg.(*lnwire.FundingLocked)
|
sentMsg, ok = msg.(*lnwire.FundingLocked)
|
||||||
|
case "Error":
|
||||||
|
sentMsg, ok = msg.(*lnwire.Error)
|
||||||
default:
|
default:
|
||||||
t.Fatalf("unknown message type: %s", msgType)
|
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",
|
t.Fatalf("expected %s to be sent, instead got error: %v",
|
||||||
msgType, lnwire.ErrorCode(errorMsg.Data[0]))
|
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
|
return sentMsg
|
||||||
@ -950,7 +955,7 @@ func assertHandleFundingLocked(t *testing.T, alice, bob *testNode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestFundingManagerNormalWorkflow(t *testing.T) {
|
func TestFundingManagerNormalWorkflow(t *testing.T) {
|
||||||
alice, bob := setupFundingManagers(t)
|
alice, bob := setupFundingManagers(t, defaultMaxPendingChannels)
|
||||||
defer tearDownFundingManagers(t, alice, bob)
|
defer tearDownFundingManagers(t, alice, bob)
|
||||||
|
|
||||||
// We will consume the channel updates as we go, so no buffering is needed.
|
// 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) {
|
func TestFundingManagerRestartBehavior(t *testing.T) {
|
||||||
alice, bob := setupFundingManagers(t)
|
alice, bob := setupFundingManagers(t, defaultMaxPendingChannels)
|
||||||
defer tearDownFundingManagers(t, alice, bob)
|
defer tearDownFundingManagers(t, alice, bob)
|
||||||
|
|
||||||
// Run through the process of opening the channel, up until the funding
|
// 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
|
// server to notify when the peer comes online, in case sending the
|
||||||
// fundingLocked message fails the first time.
|
// fundingLocked message fails the first time.
|
||||||
func TestFundingManagerOfflinePeer(t *testing.T) {
|
func TestFundingManagerOfflinePeer(t *testing.T) {
|
||||||
alice, bob := setupFundingManagers(t)
|
alice, bob := setupFundingManagers(t, defaultMaxPendingChannels)
|
||||||
defer tearDownFundingManagers(t, alice, bob)
|
defer tearDownFundingManagers(t, alice, bob)
|
||||||
|
|
||||||
// Run through the process of opening the channel, up until the funding
|
// 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
|
// will properly clean up a zombie reservation that times out after the
|
||||||
// initFundingMsg has been handled.
|
// initFundingMsg has been handled.
|
||||||
func TestFundingManagerPeerTimeoutAfterInitFunding(t *testing.T) {
|
func TestFundingManagerPeerTimeoutAfterInitFunding(t *testing.T) {
|
||||||
alice, bob := setupFundingManagers(t)
|
alice, bob := setupFundingManagers(t, defaultMaxPendingChannels)
|
||||||
defer tearDownFundingManagers(t, alice, bob)
|
defer tearDownFundingManagers(t, alice, bob)
|
||||||
|
|
||||||
// We will consume the channel updates as we go, so no buffering is needed.
|
// 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
|
// will properly clean up a zombie reservation that times out after the
|
||||||
// fundingOpenMsg has been handled.
|
// fundingOpenMsg has been handled.
|
||||||
func TestFundingManagerPeerTimeoutAfterFundingOpen(t *testing.T) {
|
func TestFundingManagerPeerTimeoutAfterFundingOpen(t *testing.T) {
|
||||||
alice, bob := setupFundingManagers(t)
|
alice, bob := setupFundingManagers(t, defaultMaxPendingChannels)
|
||||||
defer tearDownFundingManagers(t, alice, bob)
|
defer tearDownFundingManagers(t, alice, bob)
|
||||||
|
|
||||||
// We will consume the channel updates as we go, so no buffering is needed.
|
// 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
|
// will properly clean up a zombie reservation that times out after the
|
||||||
// fundingAcceptMsg has been handled.
|
// fundingAcceptMsg has been handled.
|
||||||
func TestFundingManagerPeerTimeoutAfterFundingAccept(t *testing.T) {
|
func TestFundingManagerPeerTimeoutAfterFundingAccept(t *testing.T) {
|
||||||
alice, bob := setupFundingManagers(t)
|
alice, bob := setupFundingManagers(t, defaultMaxPendingChannels)
|
||||||
defer tearDownFundingManagers(t, alice, bob)
|
defer tearDownFundingManagers(t, alice, bob)
|
||||||
|
|
||||||
// We will consume the channel updates as we go, so no buffering is needed.
|
// 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) {
|
func TestFundingManagerFundingTimeout(t *testing.T) {
|
||||||
alice, bob := setupFundingManagers(t)
|
alice, bob := setupFundingManagers(t, defaultMaxPendingChannels)
|
||||||
defer tearDownFundingManagers(t, alice, bob)
|
defer tearDownFundingManagers(t, alice, bob)
|
||||||
|
|
||||||
// We will consume the channel updates as we go, so no buffering is needed.
|
// 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.
|
// the channel initiator, that it does not timeout when the lnd restarts.
|
||||||
func TestFundingManagerFundingNotTimeoutInitiator(t *testing.T) {
|
func TestFundingManagerFundingNotTimeoutInitiator(t *testing.T) {
|
||||||
|
|
||||||
alice, bob := setupFundingManagers(t)
|
alice, bob := setupFundingManagers(t, defaultMaxPendingChannels)
|
||||||
defer tearDownFundingManagers(t, alice, bob)
|
defer tearDownFundingManagers(t, alice, bob)
|
||||||
|
|
||||||
// We will consume the channel updates as we go, so no buffering is needed.
|
// 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
|
// continues to operate as expected in case we receive a duplicate fundingLocked
|
||||||
// message.
|
// message.
|
||||||
func TestFundingManagerReceiveFundingLockedTwice(t *testing.T) {
|
func TestFundingManagerReceiveFundingLockedTwice(t *testing.T) {
|
||||||
alice, bob := setupFundingManagers(t)
|
alice, bob := setupFundingManagers(t, defaultMaxPendingChannels)
|
||||||
defer tearDownFundingManagers(t, alice, bob)
|
defer tearDownFundingManagers(t, alice, bob)
|
||||||
|
|
||||||
// We will consume the channel updates as we go, so no buffering is needed.
|
// 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
|
// handles receiving a fundingLocked after the its own fundingLocked and channel
|
||||||
// announcement is sent and gets restarted.
|
// announcement is sent and gets restarted.
|
||||||
func TestFundingManagerRestartAfterChanAnn(t *testing.T) {
|
func TestFundingManagerRestartAfterChanAnn(t *testing.T) {
|
||||||
alice, bob := setupFundingManagers(t)
|
alice, bob := setupFundingManagers(t, defaultMaxPendingChannels)
|
||||||
defer tearDownFundingManagers(t, alice, bob)
|
defer tearDownFundingManagers(t, alice, bob)
|
||||||
|
|
||||||
// We will consume the channel updates as we go, so no buffering is needed.
|
// 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
|
// fundingManager continues to operate as expected after it has received
|
||||||
// fundingLocked and then gets restarted.
|
// fundingLocked and then gets restarted.
|
||||||
func TestFundingManagerRestartAfterReceivingFundingLocked(t *testing.T) {
|
func TestFundingManagerRestartAfterReceivingFundingLocked(t *testing.T) {
|
||||||
alice, bob := setupFundingManagers(t)
|
alice, bob := setupFundingManagers(t, defaultMaxPendingChannels)
|
||||||
defer tearDownFundingManagers(t, alice, bob)
|
defer tearDownFundingManagers(t, alice, bob)
|
||||||
|
|
||||||
// We will consume the channel updates as we go, so no buffering is needed.
|
// 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),
|
// (a channel not supposed to be announced to the rest of the network),
|
||||||
// the announcementSignatures nor the nodeAnnouncement messages are sent.
|
// the announcementSignatures nor the nodeAnnouncement messages are sent.
|
||||||
func TestFundingManagerPrivateChannel(t *testing.T) {
|
func TestFundingManagerPrivateChannel(t *testing.T) {
|
||||||
alice, bob := setupFundingManagers(t)
|
alice, bob := setupFundingManagers(t, defaultMaxPendingChannels)
|
||||||
defer tearDownFundingManagers(t, alice, bob)
|
defer tearDownFundingManagers(t, alice, bob)
|
||||||
|
|
||||||
// We will consume the channel updates as we go, so no buffering is needed.
|
// 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
|
// announcement signatures nor the node announcement messages are sent upon
|
||||||
// restart.
|
// restart.
|
||||||
func TestFundingManagerPrivateRestart(t *testing.T) {
|
func TestFundingManagerPrivateRestart(t *testing.T) {
|
||||||
alice, bob := setupFundingManagers(t)
|
alice, bob := setupFundingManagers(t, defaultMaxPendingChannels)
|
||||||
defer tearDownFundingManagers(t, alice, bob)
|
defer tearDownFundingManagers(t, alice, bob)
|
||||||
|
|
||||||
// We will consume the channel updates as we go, so no buffering is needed.
|
// 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
|
// TestFundingManagerCustomChannelParameters checks that custom requirements we
|
||||||
// specify during the channel funding flow is preserved correcly on both sides.
|
// specify during the channel funding flow is preserved correcly on both sides.
|
||||||
func TestFundingManagerCustomChannelParameters(t *testing.T) {
|
func TestFundingManagerCustomChannelParameters(t *testing.T) {
|
||||||
alice, bob := setupFundingManagers(t)
|
alice, bob := setupFundingManagers(t, defaultMaxPendingChannels)
|
||||||
defer tearDownFundingManagers(t, alice, bob)
|
defer tearDownFundingManagers(t, alice, bob)
|
||||||
|
|
||||||
// This is the custom parameters we'll use.
|
// 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")
|
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