From 4aa52d267f000f84caf912c62fc14a5b8e7cacb5 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Sat, 12 Jan 2019 18:59:45 +0100 Subject: [PATCH] funding+lnwallet: ensure max_htlc_value_in_flight smaller than capacity Return an error to the remote if larger. --- fundingmanager.go | 6 ++++-- lnwallet/errors.go | 10 ++++++++++ lnwallet/interface_test.go | 16 ++++++++++++---- lnwallet/reservation.go | 14 ++++++++++++-- 4 files changed, 38 insertions(+), 8 deletions(-) diff --git a/fundingmanager.go b/fundingmanager.go index f2591206..5d18a828 100644 --- a/fundingmanager.go +++ b/fundingmanager.go @@ -1090,7 +1090,7 @@ func (f *fundingManager) handleFundingOpen(fmsg *fundingOpenMsg) { MaxAcceptedHtlcs: msg.MaxAcceptedHTLCs, CsvDelay: msg.CsvDelay, } - err = reservation.CommitConstraints(channelConstraints) + err = reservation.CommitConstraints(channelConstraints, amt) if err != nil { fndgLog.Errorf("Unacceptable channel constraints: %v", err) f.failFundingFlow(fmsg.peer, fmsg.msg.PendingChannelID, err) @@ -1254,7 +1254,9 @@ func (f *fundingManager) handleFundingAccept(fmsg *fundingAcceptMsg) { MaxAcceptedHtlcs: msg.MaxAcceptedHTLCs, CsvDelay: msg.CsvDelay, } - err = resCtx.reservation.CommitConstraints(channelConstraints) + err = resCtx.reservation.CommitConstraints( + channelConstraints, resCtx.chanAmt, + ) if err != nil { fndgLog.Warnf("Unacceptable channel constraints: %v", err) f.failFundingFlow(fmsg.peer, fmsg.msg.PendingChannelID, err) diff --git a/lnwallet/errors.go b/lnwallet/errors.go index 79ab10f7..d72caf65 100644 --- a/lnwallet/errors.go +++ b/lnwallet/errors.go @@ -132,6 +132,16 @@ func ErrNumConfsTooLarge(numConfs, maxNumConfs uint32) error { } } +// ErrMaxValueInFlightTooLarge returns an error indicating that the 'max HTLC +// value in flight' the remote required is too large to be accepted. +func ErrMaxValueInFlightTooLarge(maxValInFlight, + maxMaxValInFlight lnwire.MilliSatoshi) ReservationError { + return ReservationError{ + fmt.Errorf("maxValueInFlight too large: %v, max is %v", + maxValInFlight, maxMaxValInFlight), + } +} + // ErrChanTooSmall returns an error indicating that an incoming channel request // was too small. We'll reject any incoming channels if they're below our // configured value for the min channel size we'll accept. diff --git a/lnwallet/interface_test.go b/lnwallet/interface_test.go index 4549a266..7ed0dfe9 100644 --- a/lnwallet/interface_test.go +++ b/lnwallet/interface_test.go @@ -437,7 +437,9 @@ func testDualFundingReservationWorkflow(miner *rpctest.Harness, MaxAcceptedHtlcs: lnwallet.MaxHTLCNumber / 2, CsvDelay: csvDelay, } - err = aliceChanReservation.CommitConstraints(channelConstraints) + err = aliceChanReservation.CommitConstraints( + channelConstraints, fundingAmount*2, + ) if err != nil { t.Fatalf("unable to verify constraints: %v", err) } @@ -471,7 +473,9 @@ func testDualFundingReservationWorkflow(miner *rpctest.Harness, if err != nil { t.Fatalf("bob unable to init channel reservation: %v", err) } - err = bobChanReservation.CommitConstraints(channelConstraints) + err = bobChanReservation.CommitConstraints( + channelConstraints, fundingAmount*2, + ) if err != nil { t.Fatalf("unable to verify constraints: %v", err) } @@ -869,7 +873,9 @@ func testSingleFunderReservationWorkflow(miner *rpctest.Harness, MaxAcceptedHtlcs: lnwallet.MaxHTLCNumber / 2, CsvDelay: csvDelay, } - err = aliceChanReservation.CommitConstraints(channelConstraints) + err = aliceChanReservation.CommitConstraints( + channelConstraints, fundingAmt, + ) if err != nil { t.Fatalf("unable to verify constraints: %v", err) } @@ -903,7 +909,9 @@ func testSingleFunderReservationWorkflow(miner *rpctest.Harness, if err != nil { t.Fatalf("unable to create bob reservation: %v", err) } - err = bobChanReservation.CommitConstraints(channelConstraints) + err = bobChanReservation.CommitConstraints( + channelConstraints, fundingAmt, + ) if err != nil { t.Fatalf("unable to verify constraints: %v", err) } diff --git a/lnwallet/reservation.go b/lnwallet/reservation.go index a32acfa2..1a684f25 100644 --- a/lnwallet/reservation.go +++ b/lnwallet/reservation.go @@ -286,7 +286,9 @@ func (r *ChannelReservation) SetNumConfsRequired(numConfs uint16) { // of satoshis that can be transferred in a single commitment. This function // will also attempt to verify the constraints for sanity, returning an error // if the parameters are seemed unsound. -func (r *ChannelReservation) CommitConstraints(c *channeldb.ChannelConstraints) error { +func (r *ChannelReservation) CommitConstraints(c *channeldb.ChannelConstraints, + capacity btcutil.Amount) error { + r.Lock() defer r.Unlock() @@ -341,7 +343,15 @@ func (r *ChannelReservation) CommitConstraints(c *channeldb.ChannelConstraints) ) } - // Our dust limit should always be less than or equal to our proposed + // Fail if the maxValueInFlight is greater than the channel capacity. + capacityMsat := lnwire.NewMSatFromSatoshis(capacity) + if c.MaxPendingAmount > capacityMsat { + return ErrMaxValueInFlightTooLarge( + c.MaxPendingAmount, capacityMsat, + ) + } + + // Our dust limit should always be less than or equal our proposed // channel reserve. if r.ourContribution.DustLimit > c.ChanReserve { r.ourContribution.DustLimit = c.ChanReserve