fundingmanager+lnwallet: ensure proposed channel reserve is above dust limit
This commit is contained in:
parent
2e076ba21e
commit
3a982063a0
@ -994,10 +994,10 @@ func (f *fundingManager) handleFundingOpen(fmsg *fundingOpenMsg) {
|
|||||||
// party is attempting to dictate for our commitment transaction.
|
// party is attempting to dictate for our commitment transaction.
|
||||||
err = reservation.CommitConstraints(
|
err = reservation.CommitConstraints(
|
||||||
msg.CsvDelay, msg.MaxAcceptedHTLCs, msg.MaxValueInFlight,
|
msg.CsvDelay, msg.MaxAcceptedHTLCs, msg.MaxValueInFlight,
|
||||||
msg.HtlcMinimum, msg.ChannelReserve,
|
msg.HtlcMinimum, msg.ChannelReserve, msg.DustLimit,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fndgLog.Errorf("Unaccaptable channel constraints: %v", err)
|
fndgLog.Errorf("Unacceptable channel constraints: %v", err)
|
||||||
f.failFundingFlow(fmsg.peerAddress.IdentityKey,
|
f.failFundingFlow(fmsg.peerAddress.IdentityKey,
|
||||||
fmsg.msg.PendingChannelID, err,
|
fmsg.msg.PendingChannelID, err,
|
||||||
)
|
)
|
||||||
@ -1146,7 +1146,7 @@ func (f *fundingManager) handleFundingAccept(fmsg *fundingAcceptMsg) {
|
|||||||
resCtx.reservation.SetNumConfsRequired(uint16(msg.MinAcceptDepth))
|
resCtx.reservation.SetNumConfsRequired(uint16(msg.MinAcceptDepth))
|
||||||
err = resCtx.reservation.CommitConstraints(
|
err = resCtx.reservation.CommitConstraints(
|
||||||
msg.CsvDelay, msg.MaxAcceptedHTLCs, msg.MaxValueInFlight,
|
msg.CsvDelay, msg.MaxAcceptedHTLCs, msg.MaxValueInFlight,
|
||||||
msg.HtlcMinimum, msg.ChannelReserve,
|
msg.HtlcMinimum, msg.ChannelReserve, msg.DustLimit,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fndgLog.Warnf("Unacceptable channel constraints: %v", err)
|
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
|
// ErrChanReserveTooLarge returns an error indicating that the chan reserve the
|
||||||
// remote is requiring, is too large to be accepted.
|
// remote is requiring, is too large to be accepted.
|
||||||
func ErrChanReserveTooLarge(reserve,
|
func ErrChanReserveTooLarge(reserve,
|
||||||
|
@ -305,8 +305,14 @@ func testDualFundingReservationWorkflow(miner *rpctest.Harness,
|
|||||||
t.Fatalf("unable to initialize funding reservation: %v", err)
|
t.Fatalf("unable to initialize funding reservation: %v", err)
|
||||||
}
|
}
|
||||||
aliceChanReservation.SetNumConfsRequired(numReqConfs)
|
aliceChanReservation.SetNumConfsRequired(numReqConfs)
|
||||||
aliceChanReservation.CommitConstraints(csvDelay, lnwallet.MaxHTLCNumber/2,
|
err = aliceChanReservation.CommitConstraints(
|
||||||
lnwire.NewMSatFromSatoshis(fundingAmount), 1, 10)
|
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
|
// 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
|
// 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 {
|
if err != nil {
|
||||||
t.Fatalf("bob unable to init channel reservation: %v", err)
|
t.Fatalf("bob unable to init channel reservation: %v", err)
|
||||||
}
|
}
|
||||||
bobChanReservation.CommitConstraints(csvDelay, lnwallet.MaxHTLCNumber/2,
|
err = bobChanReservation.CommitConstraints(
|
||||||
lnwire.NewMSatFromSatoshis(fundingAmount), 1, 10)
|
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)
|
bobChanReservation.SetNumConfsRequired(numReqConfs)
|
||||||
|
|
||||||
assertContributionInitPopulated(t, bobChanReservation.OurContribution())
|
assertContributionInitPopulated(t, bobChanReservation.OurContribution())
|
||||||
@ -675,8 +687,14 @@ func testSingleFunderReservationWorkflow(miner *rpctest.Harness,
|
|||||||
t.Fatalf("unable to init channel reservation: %v", err)
|
t.Fatalf("unable to init channel reservation: %v", err)
|
||||||
}
|
}
|
||||||
aliceChanReservation.SetNumConfsRequired(numReqConfs)
|
aliceChanReservation.SetNumConfsRequired(numReqConfs)
|
||||||
aliceChanReservation.CommitConstraints(csvDelay, lnwallet.MaxHTLCNumber/2,
|
err = aliceChanReservation.CommitConstraints(
|
||||||
lnwire.NewMSatFromSatoshis(fundingAmt), 1, 10)
|
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.
|
// Verify all contribution fields have been set properly.
|
||||||
aliceContribution := aliceChanReservation.OurContribution()
|
aliceContribution := aliceChanReservation.OurContribution()
|
||||||
@ -698,8 +716,14 @@ func testSingleFunderReservationWorkflow(miner *rpctest.Harness,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create bob reservation: %v", err)
|
t.Fatalf("unable to create bob reservation: %v", err)
|
||||||
}
|
}
|
||||||
bobChanReservation.CommitConstraints(csvDelay, lnwallet.MaxHTLCNumber/2,
|
err = bobChanReservation.CommitConstraints(
|
||||||
lnwire.NewMSatFromSatoshis(fundingAmt), 1, 10)
|
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)
|
bobChanReservation.SetNumConfsRequired(numReqConfs)
|
||||||
|
|
||||||
// We'll ensure that Bob's contribution also gets generated properly.
|
// 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.
|
// if the parameters are seemed unsound.
|
||||||
func (r *ChannelReservation) CommitConstraints(csvDelay, maxHtlcs uint16,
|
func (r *ChannelReservation) CommitConstraints(csvDelay, maxHtlcs uint16,
|
||||||
maxValueInFlight, minHtlc lnwire.MilliSatoshi,
|
maxValueInFlight, minHtlc lnwire.MilliSatoshi,
|
||||||
chanReserve btcutil.Amount) error {
|
chanReserve, dustLimit btcutil.Amount) error {
|
||||||
|
|
||||||
r.Lock()
|
r.Lock()
|
||||||
defer r.Unlock()
|
defer r.Unlock()
|
||||||
@ -296,6 +296,12 @@ func (r *ChannelReservation) CommitConstraints(csvDelay, maxHtlcs uint16,
|
|||||||
return ErrCsvDelayTooLarge(csvDelay, maxDelay)
|
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
|
// Fail if we consider the channel reserve to be too large. We
|
||||||
// currently fail if it is greater than 20% of the channel capacity.
|
// currently fail if it is greater than 20% of the channel capacity.
|
||||||
maxChanReserve := r.partialState.Capacity / 5
|
maxChanReserve := r.partialState.Capacity / 5
|
||||||
@ -331,6 +337,12 @@ func (r *ChannelReservation) CommitConstraints(csvDelay, maxHtlcs uint16,
|
|||||||
minNumHtlc*minHtlc)
|
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.CsvDelay = csvDelay
|
||||||
r.ourContribution.ChannelConfig.ChanReserve = chanReserve
|
r.ourContribution.ChannelConfig.ChanReserve = chanReserve
|
||||||
r.ourContribution.ChannelConfig.MaxAcceptedHtlcs = maxHtlcs
|
r.ourContribution.ChannelConfig.MaxAcceptedHtlcs = maxHtlcs
|
||||||
|
Loading…
Reference in New Issue
Block a user