From 2f6a8b13ae31b9cd0700b8897b10fe2e0ede46b0 Mon Sep 17 00:00:00 2001 From: vctt94 Date: Wed, 29 Aug 2018 18:39:22 -0300 Subject: [PATCH] fundingmanager: Add max value to fundingmanager and fundingmanager_test --- fundingmanager.go | 20 +++++-- fundingmanager_test.go | 124 +++++++++++++++++++++++++++++++---------- rpcserver.go | 2 +- 3 files changed, 110 insertions(+), 36 deletions(-) diff --git a/fundingmanager.go b/fundingmanager.go index 22974591..ebad44b6 100644 --- a/fundingmanager.go +++ b/fundingmanager.go @@ -122,6 +122,7 @@ type reservationWithCtx struct { // Constraints we require for the remote. remoteCsvDelay uint16 remoteMinHtlc lnwire.MilliSatoshi + remoteMaxValue lnwire.MilliSatoshi updateMtx sync.RWMutex lastUpdated time.Time @@ -1376,7 +1377,7 @@ func (f *fundingManager) handleFundingOpen(fmsg *fundingOpenMsg) { // Generate our required constraints for the remote party. remoteCsvDelay := f.cfg.RequiredRemoteDelay(amt) chanReserve := f.cfg.RequiredRemoteChanReserve(amt, msg.DustLimit) - maxValue := f.cfg.RequiredRemoteMaxValue(amt) + remoteMaxValue := f.cfg.RequiredRemoteMaxValue(amt) maxHtlcs := f.cfg.RequiredRemoteMaxHTLCs(amt) minHtlc := f.cfg.DefaultMinHtlcIn @@ -1392,6 +1393,7 @@ func (f *fundingManager) handleFundingOpen(fmsg *fundingOpenMsg) { chanAmt: amt, remoteCsvDelay: remoteCsvDelay, remoteMinHtlc: minHtlc, + remoteMaxValue: remoteMaxValue, err: make(chan error, 1), peer: fmsg.peer, } @@ -1409,7 +1411,7 @@ func (f *fundingManager) handleFundingOpen(fmsg *fundingOpenMsg) { ChannelConfig: &channeldb.ChannelConfig{ ChannelConstraints: channeldb.ChannelConstraints{ DustLimit: msg.DustLimit, - MaxPendingAmount: maxValue, + MaxPendingAmount: remoteMaxValue, ChanReserve: chanReserve, MinHTLC: minHtlc, MaxAcceptedHtlcs: maxHtlcs, @@ -1451,7 +1453,7 @@ func (f *fundingManager) handleFundingOpen(fmsg *fundingOpenMsg) { fundingAccept := lnwire.AcceptChannel{ PendingChannelID: msg.PendingChannelID, DustLimit: ourContribution.DustLimit, - MaxValueInFlight: maxValue, + MaxValueInFlight: remoteMaxValue, ChannelReserve: chanReserve, MinAcceptDepth: uint32(numConfsReq), HtlcMinimum: minHtlc, @@ -1465,6 +1467,7 @@ func (f *fundingManager) handleFundingOpen(fmsg *fundingOpenMsg) { FirstCommitmentPoint: ourContribution.FirstCommitmentPoint, UpfrontShutdownScript: ourContribution.UpfrontShutdown, } + if err := fmsg.peer.SendMessage(true, &fundingAccept); err != nil { fndgLog.Errorf("unable to send funding response to peer: %v", err) f.failFundingFlow(fmsg.peer, msg.PendingChannelID, err) @@ -1540,7 +1543,6 @@ func (f *fundingManager) handleFundingAccept(fmsg *fundingAcceptMsg) { // here so we can properly commit their accepted constraints to the // reservation. chanReserve := f.cfg.RequiredRemoteChanReserve(resCtx.chanAmt, msg.DustLimit) - maxValue := f.cfg.RequiredRemoteMaxValue(resCtx.chanAmt) maxHtlcs := f.cfg.RequiredRemoteMaxHTLCs(resCtx.chanAmt) // The remote node has responded with their portion of the channel @@ -1552,7 +1554,7 @@ func (f *fundingManager) handleFundingAccept(fmsg *fundingAcceptMsg) { ChannelConfig: &channeldb.ChannelConfig{ ChannelConstraints: channeldb.ChannelConstraints{ DustLimit: msg.DustLimit, - MaxPendingAmount: maxValue, + MaxPendingAmount: resCtx.remoteMaxValue, ChanReserve: chanReserve, MinHTLC: resCtx.remoteMinHtlc, MaxAcceptedHtlcs: maxHtlcs, @@ -3065,6 +3067,7 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) { localAmt = msg.localFundingAmt minHtlcIn = msg.minHtlcIn remoteCsvDelay = msg.remoteCsvDelay + maxValue = msg.maxValueInFlight ) // We'll determine our dust limit depending on which chain is active. @@ -3198,6 +3201,11 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) { minHtlcIn = f.cfg.DefaultMinHtlcIn } + // If no max value was specified, use the default one. + if maxValue == 0 { + maxValue = f.cfg.RequiredRemoteMaxValue(capacity) + } + // If a pending channel map for this peer isn't already created, then // we create one, ultimately allowing us to track this pending // reservation within the target peer. @@ -3211,6 +3219,7 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) { chanAmt: capacity, remoteCsvDelay: remoteCsvDelay, remoteMinHtlc: minHtlcIn, + remoteMaxValue: maxValue, reservation: reservation, peer: msg.peer, updates: msg.updates, @@ -3230,7 +3239,6 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) { // policy to determine of required commitment constraints for the // remote party. chanReserve := f.cfg.RequiredRemoteChanReserve(capacity, ourDustLimit) - maxValue := f.cfg.RequiredRemoteMaxValue(capacity) maxHtlcs := f.cfg.RequiredRemoteMaxHTLCs(capacity) fndgLog.Infof("Starting funding workflow with %v for pending_id(%x), "+ diff --git a/fundingmanager_test.go b/fundingmanager_test.go index 96e2ddc2..96ccd325 100644 --- a/fundingmanager_test.go +++ b/fundingmanager_test.go @@ -961,7 +961,8 @@ func assertAddedToRouterGraph(t *testing.T, alice, bob *testNode, // advertised value will be checked against the other node's default min_htlc // value. func assertChannelAnnouncements(t *testing.T, alice, bob *testNode, - capacity btcutil.Amount, customMinHtlc ...lnwire.MilliSatoshi) { + capacity btcutil.Amount, customMinHtlc []lnwire.MilliSatoshi, + customMaxHtlc []lnwire.MilliSatoshi) { t.Helper() // After the FundingLocked message is sent, Alice and Bob will each @@ -1014,21 +1015,28 @@ func assertChannelAnnouncements(t *testing.T, alice, bob *testNode, minHtlc, m.HtlcMinimumMsat) } - // The MaxHTLC value should at this point - // _always_ be the same as the - // maxValueInFlight capacity. + maxHtlc := alice.fundingMgr.cfg.RequiredRemoteMaxValue( + capacity, + ) + // We might expect a custom MaxHltc value. + if len(customMaxHtlc) > 0 { + if len(customMaxHtlc) != 2 { + t.Fatalf("only 0 or 2 custom " + + "min htlc values " + + "currently supported") + } + + maxHtlc = customMaxHtlc[j] + } if m.MessageFlags != 1 { t.Fatalf("expected message flags to "+ "be 1, was %v", m.MessageFlags) } - maxPendingMsat := alice.fundingMgr.cfg.RequiredRemoteMaxValue( - capacity, - ) - if maxPendingMsat != m.HtlcMaximumMsat { + if maxHtlc != m.HtlcMaximumMsat { t.Fatalf("expected ChannelUpdate to "+ "advertise max HTLC %v, had %v", - maxPendingMsat, + maxHtlc, m.HtlcMaximumMsat) } @@ -1214,7 +1222,7 @@ func TestFundingManagerNormalWorkflow(t *testing.T) { // Make sure both fundingManagers send the expected channel // announcements. - assertChannelAnnouncements(t, alice, bob, capacity) + assertChannelAnnouncements(t, alice, bob, capacity, nil, nil) // Check that the state machine is updated accordingly assertAddedToRouterGraph(t, alice, bob, fundingOutPoint) @@ -1366,7 +1374,7 @@ func TestFundingManagerRestartBehavior(t *testing.T) { // Make sure both fundingManagers send the expected channel // announcements. - assertChannelAnnouncements(t, alice, bob, capacity) + assertChannelAnnouncements(t, alice, bob, capacity, nil, nil) // Check that the state machine is updated accordingly assertAddedToRouterGraph(t, alice, bob, fundingOutPoint) @@ -1504,7 +1512,7 @@ func TestFundingManagerOfflinePeer(t *testing.T) { // Make sure both fundingManagers send the expected channel // announcements. - assertChannelAnnouncements(t, alice, bob, capacity) + assertChannelAnnouncements(t, alice, bob, capacity, nil, nil) // Check that the state machine is updated accordingly assertAddedToRouterGraph(t, alice, bob, fundingOutPoint) @@ -1912,7 +1920,7 @@ func TestFundingManagerReceiveFundingLockedTwice(t *testing.T) { // Make sure both fundingManagers send the expected channel // announcements. - assertChannelAnnouncements(t, alice, bob, capacity) + assertChannelAnnouncements(t, alice, bob, capacity, nil, nil) // Check that the state machine is updated accordingly assertAddedToRouterGraph(t, alice, bob, fundingOutPoint) @@ -2015,7 +2023,7 @@ func TestFundingManagerRestartAfterChanAnn(t *testing.T) { // Make sure both fundingManagers send the expected channel // announcements. - assertChannelAnnouncements(t, alice, bob, capacity) + assertChannelAnnouncements(t, alice, bob, capacity, nil, nil) // Check that the state machine is updated accordingly assertAddedToRouterGraph(t, alice, bob, fundingOutPoint) @@ -2116,7 +2124,7 @@ func TestFundingManagerRestartAfterReceivingFundingLocked(t *testing.T) { // Make sure both fundingManagers send the expected channel // announcements. - assertChannelAnnouncements(t, alice, bob, capacity) + assertChannelAnnouncements(t, alice, bob, capacity, nil, nil) // Check that the state machine is updated accordingly assertAddedToRouterGraph(t, alice, bob, fundingOutPoint) @@ -2187,7 +2195,7 @@ func TestFundingManagerPrivateChannel(t *testing.T) { // Make sure both fundingManagers send the expected channel // announcements. - assertChannelAnnouncements(t, alice, bob, capacity) + assertChannelAnnouncements(t, alice, bob, capacity, nil, nil) // The funding transaction is now confirmed, wait for the // OpenStatusUpdate_ChanOpen update @@ -2300,7 +2308,7 @@ func TestFundingManagerPrivateRestart(t *testing.T) { // Make sure both fundingManagers send the expected channel // announcements. - assertChannelAnnouncements(t, alice, bob, capacity) + assertChannelAnnouncements(t, alice, bob, capacity, nil, nil) // Note: We don't check for the addedToRouterGraph state because in // the private channel mode, the state is quickly changed from @@ -2395,6 +2403,8 @@ func TestFundingManagerCustomChannelParameters(t *testing.T) { // This is the custom parameters we'll use. const csvDelay = 67 const minHtlcIn = 1234 + const maxValueInFlight = 50000 + const fundingAmt = 5000000 // We will consume the channel updates as we go, so no buffering is // needed. @@ -2408,15 +2418,16 @@ func TestFundingManagerCustomChannelParameters(t *testing.T) { // workflow. errChan := make(chan error, 1) initReq := &openChanReq{ - targetPubkey: bob.privKey.PubKey(), - chainHash: *activeNetParams.GenesisHash, - localFundingAmt: localAmt, - pushAmt: lnwire.NewMSatFromSatoshis(pushAmt), - private: false, - minHtlcIn: minHtlcIn, - remoteCsvDelay: csvDelay, - updates: updateChan, - err: errChan, + targetPubkey: bob.privKey.PubKey(), + chainHash: *activeNetParams.GenesisHash, + localFundingAmt: localAmt, + pushAmt: lnwire.NewMSatFromSatoshis(pushAmt), + private: false, + maxValueInFlight: maxValueInFlight, + minHtlcIn: minHtlcIn, + remoteCsvDelay: csvDelay, + updates: updateChan, + err: errChan, } alice.fundingMgr.initFundingWorkflow(bob, initReq) @@ -2455,6 +2466,12 @@ func TestFundingManagerCustomChannelParameters(t *testing.T) { minHtlcIn, openChannelReq.HtlcMinimum) } + // Check that the max value in flight is sent as part of OpenChannel. + if openChannelReq.MaxValueInFlight != maxValueInFlight { + t.Fatalf("expected OpenChannel to have MaxValueInFlight %v, got %v", + maxValueInFlight, openChannelReq.MaxValueInFlight) + } + chanID := openChannelReq.PendingChannelID // Let Bob handle the init message. @@ -2477,6 +2494,14 @@ func TestFundingManagerCustomChannelParameters(t *testing.T) { 5, acceptChannelResponse.HtlcMinimum) } + reserve := lnwire.NewMSatFromSatoshis(fundingAmt / 100) + maxValueAcceptChannel := lnwire.NewMSatFromSatoshis(fundingAmt) - reserve + + if acceptChannelResponse.MaxValueInFlight != maxValueAcceptChannel { + t.Fatalf("expected AcceptChannel to have MaxValueInFlight %v, got %v", + maxValueAcceptChannel, acceptChannelResponse.MaxValueInFlight) + } + // Forward the response to Alice. alice.fundingMgr.processFundingAccept(acceptChannelResponse, bob) @@ -2522,6 +2547,27 @@ func TestFundingManagerCustomChannelParameters(t *testing.T) { return nil } + // Helper method for checking the MaxValueInFlight stored for a + // reservation. + assertMaxHtlc := func(resCtx *reservationWithCtx, + expOurMaxValue, expTheirMaxValue lnwire.MilliSatoshi) error { + + ourMaxValue := + resCtx.reservation.OurContribution().MaxPendingAmount + if ourMaxValue != expOurMaxValue { + return fmt.Errorf("expected our maxValue to be %v, "+ + "was %v", expOurMaxValue, ourMaxValue) + } + + theirMaxValue := + resCtx.reservation.TheirContribution().MaxPendingAmount + if theirMaxValue != expTheirMaxValue { + return fmt.Errorf("expected their MaxPendingAmount to be %v, "+ + "was %v", expTheirMaxValue, theirMaxValue) + } + return nil + } + // Check that the custom channel parameters were properly set in the // channel reservation. resCtx, err := alice.fundingMgr.getReservationCtx(bobPubKey, chanID) @@ -2529,7 +2575,7 @@ func TestFundingManagerCustomChannelParameters(t *testing.T) { t.Fatalf("unable to find ctx: %v", err) } - // Alice's CSV delay should be 4 since Bob sent the fedault value, and + // Alice's CSV delay should be 4 since Bob sent the default value, and // Bob's should be 67 since Alice sent the custom value. if err := assertDelay(resCtx, 4, csvDelay); err != nil { t.Fatal(err) @@ -2541,6 +2587,14 @@ func TestFundingManagerCustomChannelParameters(t *testing.T) { t.Fatal(err) } + // The max value in flight Alice can have should be maxValueAcceptChannel, + // which is the default value and the maxium Bob can offer should be + // maxValueInFlight. + if err := assertMaxHtlc(resCtx, + maxValueAcceptChannel, maxValueInFlight); err != nil { + t.Fatal(err) + } + // Also make sure the parameters are properly set on Bob's end. resCtx, err = bob.fundingMgr.getReservationCtx(alicePubKey, chanID) if err != nil { @@ -2555,6 +2609,10 @@ func TestFundingManagerCustomChannelParameters(t *testing.T) { t.Fatal(err) } + if err := assertMaxHtlc(resCtx, + maxValueInFlight, maxValueAcceptChannel); err != nil { + t.Fatal(err) + } // Give the message to Bob. bob.fundingMgr.processFundingCreated(fundingCreated, alice) @@ -2609,10 +2667,18 @@ func TestFundingManagerCustomChannelParameters(t *testing.T) { ).(*lnwire.FundingLocked) // Make sure both fundingManagers send the expected channel - // announcements. Alice should advertise the default MinHTLC value of + // announcements. + // Alice should advertise the default MinHTLC value of // 5, while bob should advertise the value minHtlc, since Alice // required him to use it. - assertChannelAnnouncements(t, alice, bob, capacity, 5, minHtlcIn) + minHtlcArr := []lnwire.MilliSatoshi{5, minHtlcIn} + + // For maxHltc Alice should advertise the default MaxHtlc value of + // maxValueAcceptChannel, while bob should advertise the value + // maxValueInFlight since Alice required him to use it. + maxHtlcArr := []lnwire.MilliSatoshi{maxValueAcceptChannel, maxValueInFlight} + + assertChannelAnnouncements(t, alice, bob, capacity, minHtlcArr, maxHtlcArr) // The funding transaction is now confirmed, wait for the // OpenStatusUpdate_ChanOpen update diff --git a/rpcserver.go b/rpcserver.go index 1342d743..5b8e0ebd 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -1710,7 +1710,7 @@ func (r *rpcServer) parseOpenChannelReq(in *lnrpc.OpenChannelRequest, remoteInitialBalance := btcutil.Amount(in.PushSat) minHtlcIn := lnwire.MilliSatoshi(in.MinHtlcMsat) remoteCsvDelay := uint16(in.RemoteCsvDelay) - maxValue := lnwire.MilliSatoshi(in.MaxValueInFlight) + maxValue := lnwire.MilliSatoshi(in.RemoteMaxValueInFlightMsat) // Ensure that the initial balance of the remote party (if pushing // satoshis) does not exceed the amount the local party has requested