fundingmanager+lnwallet: ensure proposed channel reserve is above dust limit

This commit is contained in:
Wilmer Paulino 2018-05-14 14:04:34 -04:00
parent 2e076ba21e
commit 3a982063a0
No known key found for this signature in database
GPG Key ID: 6DF57B9F9514972F
4 changed files with 57 additions and 12 deletions

@ -994,10 +994,10 @@ func (f *fundingManager) handleFundingOpen(fmsg *fundingOpenMsg) {
// party is attempting to dictate for our commitment transaction.
err = reservation.CommitConstraints(
msg.CsvDelay, msg.MaxAcceptedHTLCs, msg.MaxValueInFlight,
msg.HtlcMinimum, msg.ChannelReserve,
msg.HtlcMinimum, msg.ChannelReserve, msg.DustLimit,
)
if err != nil {
fndgLog.Errorf("Unaccaptable channel constraints: %v", err)
fndgLog.Errorf("Unacceptable channel constraints: %v", err)
f.failFundingFlow(fmsg.peerAddress.IdentityKey,
fmsg.msg.PendingChannelID, err,
)
@ -1146,7 +1146,7 @@ func (f *fundingManager) handleFundingAccept(fmsg *fundingAcceptMsg) {
resCtx.reservation.SetNumConfsRequired(uint16(msg.MinAcceptDepth))
err = resCtx.reservation.CommitConstraints(
msg.CsvDelay, msg.MaxAcceptedHTLCs, msg.MaxValueInFlight,
msg.HtlcMinimum, msg.ChannelReserve,
msg.HtlcMinimum, msg.ChannelReserve, msg.DustLimit,
)
if err != nil {
fndgLog.Warnf("Unacceptable channel constraints: %v", err)

@ -59,6 +59,15 @@ func ErrCsvDelayTooLarge(remoteDelay, maxDelay uint16) ReservationError {
}
}
// ErrChanReserveTooSmall returns an error indicating that the channel reserve
// the remote is requiring is too small to be accepted.
func ErrChanReserveTooSmall(reserve, dustLimit btcutil.Amount) ReservationError {
return ReservationError{
fmt.Errorf("channel reserve of %v sat is too small, min is %v "+
"sat", int64(reserve), int64(dustLimit)),
}
}
// ErrChanReserveTooLarge returns an error indicating that the chan reserve the
// remote is requiring, is too large to be accepted.
func ErrChanReserveTooLarge(reserve,

@ -305,8 +305,14 @@ func testDualFundingReservationWorkflow(miner *rpctest.Harness,
t.Fatalf("unable to initialize funding reservation: %v", err)
}
aliceChanReservation.SetNumConfsRequired(numReqConfs)
aliceChanReservation.CommitConstraints(csvDelay, lnwallet.MaxHTLCNumber/2,
lnwire.NewMSatFromSatoshis(fundingAmount), 1, 10)
err = aliceChanReservation.CommitConstraints(
csvDelay, lnwallet.MaxHTLCNumber/2,
lnwire.NewMSatFromSatoshis(fundingAmount), 1, fundingAmount/100,
lnwallet.DefaultDustLimit(),
)
if err != nil {
t.Fatalf("unable to verify constraints: %v", err)
}
// 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
@ -328,8 +334,14 @@ func testDualFundingReservationWorkflow(miner *rpctest.Harness,
if err != nil {
t.Fatalf("bob unable to init channel reservation: %v", err)
}
bobChanReservation.CommitConstraints(csvDelay, lnwallet.MaxHTLCNumber/2,
lnwire.NewMSatFromSatoshis(fundingAmount), 1, 10)
err = bobChanReservation.CommitConstraints(
csvDelay, lnwallet.MaxHTLCNumber/2,
lnwire.NewMSatFromSatoshis(fundingAmount), 1, fundingAmount/100,
lnwallet.DefaultDustLimit(),
)
if err != nil {
t.Fatalf("unable to verify constraints: %v", err)
}
bobChanReservation.SetNumConfsRequired(numReqConfs)
assertContributionInitPopulated(t, bobChanReservation.OurContribution())
@ -675,8 +687,14 @@ func testSingleFunderReservationWorkflow(miner *rpctest.Harness,
t.Fatalf("unable to init channel reservation: %v", err)
}
aliceChanReservation.SetNumConfsRequired(numReqConfs)
aliceChanReservation.CommitConstraints(csvDelay, lnwallet.MaxHTLCNumber/2,
lnwire.NewMSatFromSatoshis(fundingAmt), 1, 10)
err = aliceChanReservation.CommitConstraints(
csvDelay, lnwallet.MaxHTLCNumber/2,
lnwire.NewMSatFromSatoshis(fundingAmt), 1, fundingAmt/100,
lnwallet.DefaultDustLimit(),
)
if err != nil {
t.Fatalf("unable to verify constraints: %v", err)
}
// Verify all contribution fields have been set properly.
aliceContribution := aliceChanReservation.OurContribution()
@ -698,8 +716,14 @@ func testSingleFunderReservationWorkflow(miner *rpctest.Harness,
if err != nil {
t.Fatalf("unable to create bob reservation: %v", err)
}
bobChanReservation.CommitConstraints(csvDelay, lnwallet.MaxHTLCNumber/2,
lnwire.NewMSatFromSatoshis(fundingAmt), 1, 10)
err = bobChanReservation.CommitConstraints(
csvDelay, lnwallet.MaxHTLCNumber/2,
lnwire.NewMSatFromSatoshis(fundingAmt), 1, fundingAmt/100,
lnwallet.DefaultDustLimit(),
)
if err != nil {
t.Fatalf("unable to verify constraints: %v", err)
}
bobChanReservation.SetNumConfsRequired(numReqConfs)
// We'll ensure that Bob's contribution also gets generated properly.

@ -284,7 +284,7 @@ func (r *ChannelReservation) SetNumConfsRequired(numConfs uint16) {
// if the parameters are seemed unsound.
func (r *ChannelReservation) CommitConstraints(csvDelay, maxHtlcs uint16,
maxValueInFlight, minHtlc lnwire.MilliSatoshi,
chanReserve btcutil.Amount) error {
chanReserve, dustLimit btcutil.Amount) error {
r.Lock()
defer r.Unlock()
@ -296,6 +296,12 @@ func (r *ChannelReservation) CommitConstraints(csvDelay, maxHtlcs uint16,
return ErrCsvDelayTooLarge(csvDelay, maxDelay)
}
// The dust limit should always be greater or equal to the channel
// reserve. The reservation request should be denied if otherwise.
if dustLimit > chanReserve {
return ErrChanReserveTooSmall(chanReserve, dustLimit)
}
// Fail if we consider the channel reserve to be too large. We
// currently fail if it is greater than 20% of the channel capacity.
maxChanReserve := r.partialState.Capacity / 5
@ -331,6 +337,12 @@ func (r *ChannelReservation) CommitConstraints(csvDelay, maxHtlcs uint16,
minNumHtlc*minHtlc)
}
// Our dust limit should always be less than or equal our proposed
// channel reserve.
if r.ourContribution.DustLimit > chanReserve {
r.ourContribution.DustLimit = chanReserve
}
r.ourContribution.ChannelConfig.CsvDelay = csvDelay
r.ourContribution.ChannelConfig.ChanReserve = chanReserve
r.ourContribution.ChannelConfig.MaxAcceptedHtlcs = maxHtlcs