From b422e4ec1ea208acbdab567ce09009db02308dbe Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Mon, 2 Apr 2018 16:17:50 -0700 Subject: [PATCH] lnwallet+funding+lnd: add new config option for min accepted channel size In this commit we add a new command line option (and a sane default) to allow users to specify the *smallest* inbound channel that they'll accept. Having a higher-ish limit lets users limit their channels, and also avoid a series of very low value "spam" channels. The new option is --minchansize, and expressed in satoshis. If we receive an inbound channel request for a value smaller than this, then we'll immediately reject it. --- config.go | 6 ++++-- fundingmanager.go | 43 ++++++++++++++++++++++++++++++------------- lnd.go | 1 + lnwallet/errors.go | 10 ++++++++++ 4 files changed, 45 insertions(+), 15 deletions(-) diff --git a/config.go b/config.go index 138f1d9f..9f620ac0 100644 --- a/config.go +++ b/config.go @@ -195,8 +195,9 @@ type config struct { TrickleDelay int `long:"trickledelay" description:"Time in milliseconds between each release of announcements to the network"` - Alias string `long:"alias" description:"The node alias. Used as a moniker by peers and intelligence services"` - Color string `long:"color" description:"The color of the node in hex format (i.e. '#3399FF'). Used to customize node appearance in intelligence services"` + Alias string `long:"alias" description:"The node alias. Used as a moniker by peers and intelligence services"` + Color string `long:"color" description:"The color of the node in hex format (i.e. '#3399FF'). Used to customize node appearance in intelligence services"` + MinChanSize int64 `long:"minchansize" description:"The smallest channel size (in satoshis) that we should accept. Incoming channels smaller than this will be rejected"` net torsvc.Net } @@ -264,6 +265,7 @@ func loadConfig() (*config, error) { TrickleDelay: defaultTrickleDelay, Alias: defaultAlias, Color: defaultColor, + MinChanSize: int64(minChanFundingSize), } // Pre-parse the command line options to pick up an alternative config diff --git a/fundingmanager.go b/fundingmanager.go index bc80b9f7..15e1912f 100644 --- a/fundingmanager.go +++ b/fundingmanager.go @@ -286,14 +286,14 @@ type fundingConfig struct { // times. RequiredRemoteChanReserve func(btcutil.Amount) btcutil.Amount - // RequiredRemoteMaxValue is a function closure that, given the - // channel capacity, returns the amount of MilliSatoshis that our - // remote peer can have in total outstanding HTLCs with us. + // RequiredRemoteMaxValue is a function closure that, given the channel + // capacity, returns the amount of MilliSatoshis that our remote peer + // can have in total outstanding HTLCs with us. RequiredRemoteMaxValue func(btcutil.Amount) lnwire.MilliSatoshi - // RequiredRemoteMaxHTLCs is a function closure that, given the - // channel capacity, returns the number of maximum HTLCs the remote - // peer can offer us. + // RequiredRemoteMaxHTLCs is a function closure that, given the channel + // capacity, returns the number of maximum HTLCs the remote peer can + // offer us. RequiredRemoteMaxHTLCs func(btcutil.Amount) uint16 // WatchNewChannel is to be called once a new channel enters the final @@ -308,13 +308,19 @@ type fundingConfig struct { // sub-systems. ReportShortChanID func(wire.OutPoint, lnwire.ShortChannelID) error - // ZombieSweeperInterval is the periodic time interval in which the zombie - // sweeper is run. + // ZombieSweeperInterval is the periodic time interval in which the + // zombie sweeper is run. ZombieSweeperInterval time.Duration - // ReservationTimeout is the length of idle time that must pass before a - // reservation is considered a zombie. + // ReservationTimeout is the length of idle time that must pass before + // a reservation is considered a zombie. ReservationTimeout time.Duration + + // MinChanSize is the smallest channel size that we'll accept as an + // inbound channel. We have such a parameter, as otherwise, nodes could + // flood us with very small channels that would never really be usable + // due to fees. + MinChanSize btcutil.Amount } // fundingManager acts as an orchestrator/bridge between the wallet's @@ -331,8 +337,8 @@ type fundingManager struct { started int32 stopped int32 - // cfg is a copy of the configuration struct that the FundingManager was - // initialized with. + // cfg is a copy of the configuration struct that the FundingManager + // was initialized with. cfg *fundingConfig // chanIDKey is a cryptographically random key that's used to generate @@ -939,7 +945,18 @@ func (f *fundingManager) handleFundingOpen(fmsg *fundingOpenMsg) { if msg.FundingAmount > maxFundingAmount { f.failFundingFlow( fmsg.peerAddress.IdentityKey, fmsg.msg.PendingChannelID, - lnwire.ErrChanTooLarge) + lnwire.ErrChanTooLarge, + ) + return + } + + // We'll, also ensure that the remote party isn't attempting to propose + // a channel that's below our current min channel size. + if amt < f.cfg.MinChanSize { + f.failFundingFlow( + fmsg.peerAddress.IdentityKey, fmsg.msg.PendingChannelID, + lnwallet.ErrChanTooSmall(amt, btcutil.Amount(f.cfg.MinChanSize)), + ) return } diff --git a/lnd.go b/lnd.go index 9a0f767f..ce6ee7f0 100644 --- a/lnd.go +++ b/lnd.go @@ -470,6 +470,7 @@ func lndMain() error { }, ZombieSweeperInterval: 1 * time.Minute, ReservationTimeout: 10 * time.Minute, + MinChanSize: btcutil.Amount(cfg.MinChanSize), }) if err != nil { return err diff --git a/lnwallet/errors.go b/lnwallet/errors.go index 396cdd8a..1e113473 100644 --- a/lnwallet/errors.go +++ b/lnwallet/errors.go @@ -106,3 +106,13 @@ func ErrMaxValueInFlightTooSmall(maxValInFlight, maxValInFlight, minMaxValInFlight), } } + +// 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. +func ErrChanTooSmall(chanSize, minChanSize btcutil.Amount) ReservationError { + return ReservationError{ + fmt.Errorf("chan size of %v is below min chan size of %v", + chanSize, minChanSize), + } +}