From 535947693688db4b892962c4c83f31ef65f7c1c6 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 12 Sep 2017 17:41:40 +0200 Subject: [PATCH] lnwallet: add new methods to ChannelReservation for dealing w/ chan constraints This commit adds to methods to the ChannelReservation struct: one for generating the channel constraints we require for the remote party, and one for validating their desired constraints, and committing them to our ChannelConfig. With these two new methods, we can now begin to properly store and adhere to the current set of channel flow control constraints. --- lnwallet/interface_test.go | 12 +++++++---- lnwallet/reservation.go | 44 ++++++++++++++++++++++++++++++++------ 2 files changed, 46 insertions(+), 10 deletions(-) diff --git a/lnwallet/interface_test.go b/lnwallet/interface_test.go index c008492c..eb030128 100644 --- a/lnwallet/interface_test.go +++ b/lnwallet/interface_test.go @@ -261,7 +261,8 @@ func testDualFundingReservationWorkflow(miner *rpctest.Harness, t.Fatalf("unable to initialize funding reservation: %v", err) } aliceChanReservation.SetNumConfsRequired(numReqConfs) - aliceChanReservation.RequireLocalDelay(csvDelay) + aliceChanReservation.CommitConstraints(csvDelay, lnwallet.MaxHTLCNumber/2, + lnwire.NewMSatFromSatoshis(fundingAmount), 10) // The channel reservation should now be populated with a multi-sig key // from our HD chain, a change output with 3 BTC, and 2 outputs @@ -283,7 +284,8 @@ func testDualFundingReservationWorkflow(miner *rpctest.Harness, if err != nil { t.Fatalf("bob unable to init channel reservation: %v", err) } - bobChanReservation.RequireLocalDelay(csvDelay) + bobChanReservation.CommitConstraints(csvDelay, lnwallet.MaxHTLCNumber/2, + lnwire.NewMSatFromSatoshis(fundingAmount), 10) bobChanReservation.SetNumConfsRequired(numReqConfs) assertContributionInitPopulated(t, bobChanReservation.OurContribution()) @@ -551,7 +553,8 @@ func testSingleFunderReservationWorkflow(miner *rpctest.Harness, t.Fatalf("unable to init channel reservation: %v", err) } aliceChanReservation.SetNumConfsRequired(numReqConfs) - aliceChanReservation.RequireLocalDelay(csvDelay) + aliceChanReservation.CommitConstraints(csvDelay, lnwallet.MaxHTLCNumber/2, + lnwire.NewMSatFromSatoshis(fundingAmt), 10) // Verify all contribution fields have been set properly. aliceContribution := aliceChanReservation.OurContribution() @@ -573,7 +576,8 @@ func testSingleFunderReservationWorkflow(miner *rpctest.Harness, if err != nil { t.Fatalf("unable to create bob reservation: %v", err) } - bobChanReservation.RequireLocalDelay(csvDelay) + bobChanReservation.CommitConstraints(csvDelay, lnwallet.MaxHTLCNumber/2, + lnwire.NewMSatFromSatoshis(fundingAmt), 10) bobChanReservation.SetNumConfsRequired(numReqConfs) // We'll ensure that Bob's contribution also gets generated properly. diff --git a/lnwallet/reservation.go b/lnwallet/reservation.go index 017b69ac..3cf5dbe3 100644 --- a/lnwallet/reservation.go +++ b/lnwallet/reservation.go @@ -236,16 +236,48 @@ func (r *ChannelReservation) SetNumConfsRequired(numConfs uint16) { r.partialState.NumConfsRequired = numConfs } -// RequireLocalDelay sets the mandatory CSV delay that MUST be used when -// creating the local commitment transaction. This is distinct from the normal -// reservation workflow as the remote party will dictate this value for us. -// -// TODO(roasbeef): abstract out dictation of params remote side gives -func (r *ChannelReservation) RequireLocalDelay(csvDelay uint16) { +// CommitConstraints takes the constraints that the remote party specifies for +// the type of commitments that we can generate for them. These constraints +// include several parameters that serve as flow control restricting the amount +// 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(csvDelay, maxHtlcs uint16, + maxValueInFlight lnwire.MilliSatoshi, chanReserve btcutil.Amount) error { + r.Lock() defer r.Unlock() r.ourContribution.ChannelConfig.CsvDelay = csvDelay + r.ourContribution.ChannelConfig.ChanReserve = chanReserve + r.ourContribution.ChannelConfig.MaxAcceptedHtlcs = maxHtlcs + r.ourContribution.ChannelConfig.MaxPendingAmount = maxValueInFlight + + return nil +} + +// RemoteChanConstraints returns our desired parameters which constraint the +// type of commitment transactions that the remote party can extend for our +// current state. In order to ensure that we only accept sane states, we'll +// specify: the required reserve the remote party must uphold, the max value in +// flight, and the maximum number of HTLC's that can propose in a state. +func (r *ChannelReservation) RemoteChanConstraints() (btcutil.Amount, lnwire.MilliSatoshi, uint16) { + chanCapacity := r.partialState.Capacity + + // TODO(roasbeef): move csv delay calculation into func? + + // By default, we'll require them to maintain at least 1% of thee total + // channel capacity at all times. + chanReserve := (chanCapacity + 99) / 100 + + // We'll allow them to fully utilize the full bandwidth of the channel, + // minus our required reserve. + maxValue := lnwire.NewMSatFromSatoshis(chanCapacity - chanReserve) + + // Finally, we'll permit them to utilize the full channel bandwidth + maxHTLCs := uint16(MaxHTLCNumber / 2) + + return chanReserve, maxValue, maxHTLCs } // OurContribution returns the wallet's fully populated contribution to the