diff --git a/fundingmanager.go b/fundingmanager.go index 3f67db0c3..bfd3f0174 100644 --- a/fundingmanager.go +++ b/fundingmanager.go @@ -337,6 +337,14 @@ type fundingConfig struct { // due to fees. MinChanSize btcutil.Amount + // MaxPendingChannels is the maximum number of pending channels we + // allow for each peer. + MaxPendingChannels int + + // RejectPush is set true if the fundingmanager should reject any + // incoming channels having a non-zero push amount. + RejectPush bool + // NotifyOpenChannelEvent informs the ChannelNotifier when channels // transition from pending open to open. NotifyOpenChannelEvent func(wire.OutPoint) @@ -1012,7 +1020,7 @@ func (f *fundingManager) handleFundingOpen(fmsg *fundingOpenMsg) { // TODO(roasbeef): modify to only accept a _single_ pending channel per // block unless white listed - if numPending >= cfg.MaxPendingChannels { + if numPending >= f.cfg.MaxPendingChannels { f.failFundingFlow( fmsg.peer, fmsg.msg.PendingChannelID, lnwire.ErrMaxPendingChannels, @@ -1057,7 +1065,7 @@ func (f *fundingManager) handleFundingOpen(fmsg *fundingOpenMsg) { // If request specifies non-zero push amount and 'rejectpush' is set, // signal an error. - if cfg.RejectPush && msg.PushAmount > 0 { + if f.cfg.RejectPush && msg.PushAmount > 0 { f.failFundingFlow( fmsg.peer, fmsg.msg.PendingChannelID, lnwallet.ErrNonZeroPushAmount()) diff --git a/fundingmanager_test.go b/fundingmanager_test.go index 891f5eabf..5416304b8 100644 --- a/fundingmanager_test.go +++ b/fundingmanager_test.go @@ -236,7 +236,8 @@ func createTestWallet(cdb *channeldb.DB, netParams *chaincfg.Params, } func createTestFundingManager(t *testing.T, privKey *btcec.PrivateKey, - addr *lnwire.NetAddress, tempTestDir string) (*testNode, error) { + addr *lnwire.NetAddress, tempTestDir string, + options ...cfgOption) (*testNode, error) { netParams := activeNetParams.Params estimator := lnwallet.NewStaticFeeEstimator(62500, 0) @@ -282,7 +283,7 @@ func createTestFundingManager(t *testing.T, privKey *btcec.PrivateKey, var chanIDSeed [32]byte - f, err := newFundingManager(fundingConfig{ + fundingCfg := fundingConfig{ IDKey: privKey.PubKey(), Wallet: lnw, Notifier: chainNotifier, @@ -363,8 +364,15 @@ func createTestFundingManager(t *testing.T, privKey *btcec.PrivateKey, }, ZombieSweeperInterval: 1 * time.Hour, ReservationTimeout: 1 * time.Nanosecond, + MaxPendingChannels: DefaultMaxPendingChannels, NotifyOpenChannelEvent: func(wire.OutPoint) {}, - }) + } + + for _, op := range options { + op(&fundingCfg) + } + + f, err := newFundingManager(fundingCfg) if err != nil { t.Fatalf("failed creating fundingManager: %v", err) } @@ -468,12 +476,10 @@ func recreateAliceFundingManager(t *testing.T, alice *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: maxPendingChannels, - } +type cfgOption func(*fundingConfig) + +func setupFundingManagers(t *testing.T, + options ...cfgOption) (*testNode, *testNode) { aliceTestDir, err := ioutil.TempDir("", "alicelnwallet") if err != nil { @@ -481,7 +487,7 @@ func setupFundingManagers(t *testing.T, maxPendingChannels int) (*testNode, *tes } alice, err := createTestFundingManager( - t, alicePrivKey, aliceAddr, aliceTestDir, + t, alicePrivKey, aliceAddr, aliceTestDir, options..., ) if err != nil { t.Fatalf("failed creating fundingManager: %v", err) @@ -492,7 +498,9 @@ func setupFundingManagers(t *testing.T, maxPendingChannels int) (*testNode, *tes t.Fatalf("unable to create temp directory: %v", err) } - bob, err := createTestFundingManager(t, bobPrivKey, bobAddr, bobTestDir) + bob, err := createTestFundingManager( + t, bobPrivKey, bobAddr, bobTestDir, options..., + ) if err != nil { t.Fatalf("failed creating fundingManager: %v", err) } @@ -1029,7 +1037,7 @@ func assertHandleFundingLocked(t *testing.T, alice, bob *testNode) { } func TestFundingManagerNormalWorkflow(t *testing.T) { - alice, bob := setupFundingManagers(t, DefaultMaxPendingChannels) + alice, bob := setupFundingManagers(t) defer tearDownFundingManagers(t, alice, bob) // We will consume the channel updates as we go, so no buffering is needed. @@ -1102,7 +1110,7 @@ func TestFundingManagerNormalWorkflow(t *testing.T) { } func TestFundingManagerRestartBehavior(t *testing.T) { - alice, bob := setupFundingManagers(t, DefaultMaxPendingChannels) + alice, bob := setupFundingManagers(t) defer tearDownFundingManagers(t, alice, bob) // Run through the process of opening the channel, up until the funding @@ -1240,7 +1248,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, DefaultMaxPendingChannels) + alice, bob := setupFundingManagers(t) defer tearDownFundingManagers(t, alice, bob) // Run through the process of opening the channel, up until the funding @@ -1374,7 +1382,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, DefaultMaxPendingChannels) + alice, bob := setupFundingManagers(t) defer tearDownFundingManagers(t, alice, bob) // We will consume the channel updates as we go, so no buffering is needed. @@ -1434,7 +1442,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, DefaultMaxPendingChannels) + alice, bob := setupFundingManagers(t) defer tearDownFundingManagers(t, alice, bob) // We will consume the channel updates as we go, so no buffering is needed. @@ -1503,7 +1511,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, DefaultMaxPendingChannels) + alice, bob := setupFundingManagers(t) defer tearDownFundingManagers(t, alice, bob) // We will consume the channel updates as we go, so no buffering is needed. @@ -1577,7 +1585,7 @@ func TestFundingManagerPeerTimeoutAfterFundingAccept(t *testing.T) { } func TestFundingManagerFundingTimeout(t *testing.T) { - alice, bob := setupFundingManagers(t, DefaultMaxPendingChannels) + alice, bob := setupFundingManagers(t) defer tearDownFundingManagers(t, alice, bob) // We will consume the channel updates as we go, so no buffering is needed. @@ -1622,7 +1630,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, DefaultMaxPendingChannels) + alice, bob := setupFundingManagers(t) defer tearDownFundingManagers(t, alice, bob) // We will consume the channel updates as we go, so no buffering is needed. @@ -1689,7 +1697,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, DefaultMaxPendingChannels) + alice, bob := setupFundingManagers(t) defer tearDownFundingManagers(t, alice, bob) // We will consume the channel updates as we go, so no buffering is needed. @@ -1781,7 +1789,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, DefaultMaxPendingChannels) + alice, bob := setupFundingManagers(t) defer tearDownFundingManagers(t, alice, bob) // We will consume the channel updates as we go, so no buffering is needed. @@ -1858,7 +1866,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, DefaultMaxPendingChannels) + alice, bob := setupFundingManagers(t) defer tearDownFundingManagers(t, alice, bob) // We will consume the channel updates as we go, so no buffering is needed. @@ -1931,7 +1939,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, DefaultMaxPendingChannels) + alice, bob := setupFundingManagers(t) defer tearDownFundingManagers(t, alice, bob) // We will consume the channel updates as we go, so no buffering is needed. @@ -2033,7 +2041,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, DefaultMaxPendingChannels) + alice, bob := setupFundingManagers(t) defer tearDownFundingManagers(t, alice, bob) // We will consume the channel updates as we go, so no buffering is needed. @@ -2155,7 +2163,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, DefaultMaxPendingChannels) + alice, bob := setupFundingManagers(t) defer tearDownFundingManagers(t, alice, bob) // This is the custom parameters we'll use. @@ -2385,7 +2393,11 @@ func TestFundingManagerCustomChannelParameters(t *testing.T) { func TestFundingManagerMaxPendingChannels(t *testing.T) { const maxPending = 4 - alice, bob := setupFundingManagers(t, maxPending) + alice, bob := setupFundingManagers( + t, func(cfg *fundingConfig) { + cfg.MaxPendingChannels = maxPending + }, + ) defer tearDownFundingManagers(t, alice, bob) // Create openChanReqs for maxPending+1 channels. @@ -2545,13 +2557,12 @@ func TestFundingManagerMaxPendingChannels(t *testing.T) { // option, namely that non-zero incoming push amounts are disabled. func TestFundingManagerRejectPush(t *testing.T) { // Enable 'rejectpush' option and initialize funding managers. - alice, bob := setupFundingManagers(t, DefaultMaxPendingChannels) - rejectPush := cfg.RejectPush - cfg.RejectPush = true - defer func() { - tearDownFundingManagers(t, alice, bob) - cfg.RejectPush = rejectPush - }() + alice, bob := setupFundingManagers( + t, func(cfg *fundingConfig) { + cfg.RejectPush = true + }, + ) + defer tearDownFundingManagers(t, alice, bob) // Create a funding request and start the workflow. updateChan := make(chan *lnrpc.OpenStatusUpdate) @@ -2607,7 +2618,7 @@ func TestFundingManagerRejectPush(t *testing.T) { func TestFundingManagerMaxConfs(t *testing.T) { t.Parallel() - alice, bob := setupFundingManagers(t, DefaultMaxPendingChannels) + alice, bob := setupFundingManagers(t) defer tearDownFundingManagers(t, alice, bob) // Create a funding request and start the workflow. diff --git a/server.go b/server.go index 64b376663..a5e97ea60 100644 --- a/server.go +++ b/server.go @@ -1051,6 +1051,8 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, ZombieSweeperInterval: 1 * time.Minute, ReservationTimeout: 10 * time.Minute, MinChanSize: btcutil.Amount(cfg.MinChanSize), + MaxPendingChannels: cfg.MaxPendingChannels, + RejectPush: cfg.RejectPush, NotifyOpenChannelEvent: s.channelNotifier.NotifyOpenChannelEvent, }) if err != nil {