Merge pull request #2275 from wpaulino/funding-max-confs
fundingmanager: rejects funding requests with number of confirmations too large
This commit is contained in:
20 files changed
+285
-122
No files matched your search
@@ -123,6 +123,15 @@ func ErrMaxValueInFlightTooSmall(maxValInFlight,
|
||||
}
|
||||
}
|
||||
|
||||
// ErrNumConfsTooLarge returns an error indicating that the number of
|
||||
// confirmations required for a channel is too large.
|
||||
func ErrNumConfsTooLarge(numConfs, maxNumConfs uint32) error {
|
||||
return ReservationError{
|
||||
fmt.Errorf("minimum depth of %d is too large, max is %d",
|
||||
numConfs, maxNumConfs),
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
|
||||
+20
-20
@@ -429,11 +429,15 @@ func testDualFundingReservationWorkflow(miner *rpctest.Harness,
|
||||
t.Fatalf("unable to initialize funding reservation: %v", err)
|
||||
}
|
||||
aliceChanReservation.SetNumConfsRequired(numReqConfs)
|
||||
err = aliceChanReservation.CommitConstraints(
|
||||
csvDelay, lnwallet.MaxHTLCNumber/2,
|
||||
lnwire.NewMSatFromSatoshis(fundingAmount), 1, fundingAmount/100,
|
||||
lnwallet.DefaultDustLimit(),
|
||||
)
|
||||
channelConstraints := &channeldb.ChannelConstraints{
|
||||
DustLimit: lnwallet.DefaultDustLimit(),
|
||||
ChanReserve: fundingAmount / 100,
|
||||
MaxPendingAmount: lnwire.NewMSatFromSatoshis(fundingAmount),
|
||||
MinHTLC: 1,
|
||||
MaxAcceptedHtlcs: lnwallet.MaxHTLCNumber / 2,
|
||||
CsvDelay: csvDelay,
|
||||
}
|
||||
err = aliceChanReservation.CommitConstraints(channelConstraints)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to verify constraints: %v", err)
|
||||
}
|
||||
@@ -467,11 +471,7 @@ func testDualFundingReservationWorkflow(miner *rpctest.Harness,
|
||||
if err != nil {
|
||||
t.Fatalf("bob unable to init channel reservation: %v", err)
|
||||
}
|
||||
err = bobChanReservation.CommitConstraints(
|
||||
csvDelay, lnwallet.MaxHTLCNumber/2,
|
||||
lnwire.NewMSatFromSatoshis(fundingAmount), 1, fundingAmount/100,
|
||||
lnwallet.DefaultDustLimit(),
|
||||
)
|
||||
err = bobChanReservation.CommitConstraints(channelConstraints)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to verify constraints: %v", err)
|
||||
}
|
||||
@@ -861,11 +861,15 @@ func testSingleFunderReservationWorkflow(miner *rpctest.Harness,
|
||||
t.Fatalf("unable to init channel reservation: %v", err)
|
||||
}
|
||||
aliceChanReservation.SetNumConfsRequired(numReqConfs)
|
||||
err = aliceChanReservation.CommitConstraints(
|
||||
csvDelay, lnwallet.MaxHTLCNumber/2,
|
||||
lnwire.NewMSatFromSatoshis(fundingAmt), 1, fundingAmt/100,
|
||||
lnwallet.DefaultDustLimit(),
|
||||
)
|
||||
channelConstraints := &channeldb.ChannelConstraints{
|
||||
DustLimit: lnwallet.DefaultDustLimit(),
|
||||
ChanReserve: fundingAmt / 100,
|
||||
MaxPendingAmount: lnwire.NewMSatFromSatoshis(fundingAmt),
|
||||
MinHTLC: 1,
|
||||
MaxAcceptedHtlcs: lnwallet.MaxHTLCNumber / 2,
|
||||
CsvDelay: csvDelay,
|
||||
}
|
||||
err = aliceChanReservation.CommitConstraints(channelConstraints)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to verify constraints: %v", err)
|
||||
}
|
||||
@@ -899,11 +903,7 @@ func testSingleFunderReservationWorkflow(miner *rpctest.Harness,
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create bob reservation: %v", err)
|
||||
}
|
||||
err = bobChanReservation.CommitConstraints(
|
||||
csvDelay, lnwallet.MaxHTLCNumber/2,
|
||||
lnwire.NewMSatFromSatoshis(fundingAmt), 1, fundingAmt/100,
|
||||
lnwallet.DefaultDustLimit(),
|
||||
)
|
||||
err = bobChanReservation.CommitConstraints(channelConstraints)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to verify constraints: %v", err)
|
||||
}
|
||||
|
||||
+27
-27
@@ -282,72 +282,72 @@ 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(csvDelay, maxHtlcs uint16,
|
||||
maxValueInFlight, minHtlc lnwire.MilliSatoshi,
|
||||
chanReserve, dustLimit btcutil.Amount) error {
|
||||
|
||||
func (r *ChannelReservation) CommitConstraints(c *channeldb.ChannelConstraints) error {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
|
||||
// Fail if we consider csvDelay excessively large.
|
||||
// TODO(halseth): find a more scientific choice of value.
|
||||
const maxDelay = 10000
|
||||
if csvDelay > maxDelay {
|
||||
return ErrCsvDelayTooLarge(csvDelay, maxDelay)
|
||||
if c.CsvDelay > maxDelay {
|
||||
return ErrCsvDelayTooLarge(c.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)
|
||||
if c.DustLimit > c.ChanReserve {
|
||||
return ErrChanReserveTooSmall(c.ChanReserve, c.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
|
||||
if chanReserve > maxChanReserve {
|
||||
return ErrChanReserveTooLarge(chanReserve, maxChanReserve)
|
||||
if c.ChanReserve > maxChanReserve {
|
||||
return ErrChanReserveTooLarge(c.ChanReserve, maxChanReserve)
|
||||
}
|
||||
|
||||
// Fail if the minimum HTLC value is too large. If this is too large,
|
||||
// the channel won't be useful for sending small payments. This limit
|
||||
// is currently set to maxValueInFlight, effectively letting the remote
|
||||
// setting this as large as it wants.
|
||||
if minHtlc > maxValueInFlight {
|
||||
return ErrMinHtlcTooLarge(minHtlc, maxValueInFlight)
|
||||
if c.MinHTLC > c.MaxPendingAmount {
|
||||
return ErrMinHtlcTooLarge(c.MinHTLC, c.MaxPendingAmount)
|
||||
}
|
||||
|
||||
// Fail if maxHtlcs is above the maximum allowed number of 483. This
|
||||
// number is specified in BOLT-02.
|
||||
if maxHtlcs > uint16(MaxHTLCNumber/2) {
|
||||
return ErrMaxHtlcNumTooLarge(maxHtlcs, uint16(MaxHTLCNumber/2))
|
||||
if c.MaxAcceptedHtlcs > uint16(MaxHTLCNumber/2) {
|
||||
return ErrMaxHtlcNumTooLarge(
|
||||
c.MaxAcceptedHtlcs, uint16(MaxHTLCNumber/2),
|
||||
)
|
||||
}
|
||||
|
||||
// Fail if we consider maxHtlcs too small. If this is too small we
|
||||
// cannot offer many HTLCs to the remote.
|
||||
const minNumHtlc = 5
|
||||
if maxHtlcs < minNumHtlc {
|
||||
return ErrMaxHtlcNumTooSmall(maxHtlcs, minNumHtlc)
|
||||
if c.MaxAcceptedHtlcs < minNumHtlc {
|
||||
return ErrMaxHtlcNumTooSmall(c.MaxAcceptedHtlcs, minNumHtlc)
|
||||
}
|
||||
|
||||
// Fail if we consider maxValueInFlight too small. We currently require
|
||||
// the remote to at least allow minNumHtlc * minHtlc in flight.
|
||||
if maxValueInFlight < minNumHtlc*minHtlc {
|
||||
return ErrMaxValueInFlightTooSmall(maxValueInFlight,
|
||||
minNumHtlc*minHtlc)
|
||||
if c.MaxPendingAmount < minNumHtlc*c.MinHTLC {
|
||||
return ErrMaxValueInFlightTooSmall(
|
||||
c.MaxPendingAmount, minNumHtlc*c.MinHTLC,
|
||||
)
|
||||
}
|
||||
|
||||
// Our dust limit should always be less than or equal our proposed
|
||||
// Our dust limit should always be less than or equal to our proposed
|
||||
// channel reserve.
|
||||
if r.ourContribution.DustLimit > chanReserve {
|
||||
r.ourContribution.DustLimit = chanReserve
|
||||
if r.ourContribution.DustLimit > c.ChanReserve {
|
||||
r.ourContribution.DustLimit = c.ChanReserve
|
||||
}
|
||||
|
||||
r.ourContribution.ChannelConfig.CsvDelay = csvDelay
|
||||
r.ourContribution.ChannelConfig.ChanReserve = chanReserve
|
||||
r.ourContribution.ChannelConfig.MaxAcceptedHtlcs = maxHtlcs
|
||||
r.ourContribution.ChannelConfig.MaxPendingAmount = maxValueInFlight
|
||||
r.ourContribution.ChannelConfig.MinHTLC = minHtlc
|
||||
r.ourContribution.ChanReserve = c.ChanReserve
|
||||
r.ourContribution.MaxPendingAmount = c.MaxPendingAmount
|
||||
r.ourContribution.MinHTLC = c.MinHTLC
|
||||
r.ourContribution.MaxAcceptedHtlcs = c.MaxAcceptedHtlcs
|
||||
r.ourContribution.CsvDelay = c.CsvDelay
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -144,8 +144,8 @@ func CreateTestChannels() (*LightningChannel, *LightningChannel, func(), error)
|
||||
ChanReserve: channelCapacity / 100,
|
||||
MinHTLC: 0,
|
||||
MaxAcceptedHtlcs: MaxHTLCNumber / 2,
|
||||
CsvDelay: uint16(csvTimeoutAlice),
|
||||
},
|
||||
CsvDelay: uint16(csvTimeoutAlice),
|
||||
MultiSigKey: keychain.KeyDescriptor{
|
||||
PubKey: aliceKeys[0].PubKey(),
|
||||
},
|
||||
@@ -169,8 +169,8 @@ func CreateTestChannels() (*LightningChannel, *LightningChannel, func(), error)
|
||||
ChanReserve: channelCapacity / 100,
|
||||
MinHTLC: 0,
|
||||
MaxAcceptedHtlcs: MaxHTLCNumber / 2,
|
||||
CsvDelay: uint16(csvTimeoutBob),
|
||||
},
|
||||
CsvDelay: uint16(csvTimeoutBob),
|
||||
MultiSigKey: keychain.KeyDescriptor{
|
||||
PubKey: bobKeys[0].PubKey(),
|
||||
},
|
||||
|
||||
@@ -379,8 +379,8 @@ func TestCommitmentAndHTLCTransactions(t *testing.T) {
|
||||
DustLimit: tc.dustLimit,
|
||||
MaxPendingAmount: lnwire.NewMSatFromSatoshis(tc.fundingAmount),
|
||||
MaxAcceptedHtlcs: MaxHTLCNumber,
|
||||
CsvDelay: tc.localCsvDelay,
|
||||
},
|
||||
CsvDelay: tc.localCsvDelay,
|
||||
MultiSigKey: keychain.KeyDescriptor{
|
||||
PubKey: tc.localFundingPubKey,
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user