diff --git a/config.go b/config.go index 3bc244468..85cdc09d0 100644 --- a/config.go +++ b/config.go @@ -721,6 +721,7 @@ func DefaultConfig() Config { MsgBurstBytes: discovery.DefaultMsgBytesBurst, FilterConcurrency: discovery.DefaultFilterConcurrency, BanThreshold: discovery.DefaultBanThreshold, + PeerMsgRateBytes: discovery.DefaultPeerMsgBytesPerSecond, }, Invoices: &lncfg.Invoices{ HoldExpiryDelta: lncfg.DefaultHoldInvoiceExpiryDelta, diff --git a/discovery/gossiper.go b/discovery/gossiper.go index 967f9ee94..c720a6129 100644 --- a/discovery/gossiper.go +++ b/discovery/gossiper.go @@ -407,6 +407,10 @@ type Config struct { // BanThreshold is the score used to decide whether a given peer is // banned or not. BanThreshold uint64 + + // PeerMsgRateBytes is the rate limit for the number of bytes per second + // that we'll allocate to outbound gossip messages for a single peer. + PeerMsgRateBytes uint64 } // processedNetworkMsg is a wrapper around networkMsg and a boolean. It is @@ -609,6 +613,7 @@ func New(cfg Config, selfKeyDesc *keychain.KeyDescriptor) *AuthenticatedGossiper AllotedMsgBytesPerSecond: cfg.MsgRateBytes, AllotedMsgBytesBurst: cfg.MsgBurstBytes, FilterConcurrency: cfg.FilterConcurrency, + PeerMsgBytesPerSecond: cfg.PeerMsgRateBytes, }) gossiper.reliableSender = newReliableSender(&reliableSenderCfg{ diff --git a/discovery/sync_manager.go b/discovery/sync_manager.go index 2cc1bd949..56e81e64e 100644 --- a/discovery/sync_manager.go +++ b/discovery/sync_manager.go @@ -146,6 +146,11 @@ type SyncManagerCfg struct { // FilterConcurrency is the maximum number of concurrent gossip filter // applications that can be processed. If not set, defaults to 5. FilterConcurrency int + + // PeerMsgBytesPerSecond is the allotted bandwidth rate, expressed in + // bytes/second that a single gossip syncer can consume. Once we exceed + // this rate, message sending will block until we're below the rate. + PeerMsgBytesPerSecond uint64 } // SyncManager is a subsystem of the gossiper that manages the gossip syncers @@ -674,6 +679,7 @@ func (m *SyncManager) createGossipSyncer(peer lnpeer.Peer) *GossipSyncer { maxQueryChanRangeReplies: maxQueryChanRangeReplies, noTimestampQueryOption: m.cfg.NoTimestampQueries, isStillZombieChannel: m.cfg.IsStillZombieChannel, + msgBytesPerSecond: m.cfg.PeerMsgBytesPerSecond, }, m.gossipFilterSema) // Gossip syncers are initialized by default in a PassiveSync type diff --git a/lncfg/gossip.go b/lncfg/gossip.go index 635496c0b..8793f7895 100644 --- a/lncfg/gossip.go +++ b/lncfg/gossip.go @@ -41,6 +41,8 @@ type Gossip struct { FilterConcurrency int `long:"filter-concurrency" description:"The maximum number of concurrent gossip filter applications that can be processed. If not set, defaults to 5."` BanThreshold uint64 `long:"ban-threshold" description:"The score at which a peer is banned. A peer's ban score is incremented for each invalid gossip message. Invalid messages include those with bad signatures, stale timestamps, excessive updates, or invalid chain data. Once the score reaches this threshold, the peer is banned. Set to 0 to disable banning."` + + PeerMsgRateBytes uint64 `long:"peer-msg-rate-bytes" description:"The peer-specific rate of outbound gossip messages, expressed in bytes per second. This setting controls the long-term average speed of gossip traffic sent from your node. The rate limit is applied to each peer. If the rate of outgoing messages exceeds this value, lnd will start to queue and delay messages sending to that peer to stay within the limit."` } // Parse the pubkeys for the pinned syncers. @@ -72,6 +74,12 @@ func (g *Gossip) Validate() error { g.MsgBurstBytes, lnwire.MaxSliceLength) } + if g.MsgRateBytes < g.PeerMsgRateBytes { + return fmt.Errorf("msg-rate-bytes=%v must be at greater than "+ + "peer-msg-rate-bytes=%v", g.MsgRateBytes, + g.PeerMsgRateBytes) + } + return nil } diff --git a/sample-lnd.conf b/sample-lnd.conf index bc6f07fa2..6b2ca8a1c 100644 --- a/sample-lnd.conf +++ b/sample-lnd.conf @@ -1814,6 +1814,13 @@ ; ; gossip.ban-threshold=100 +; The peer-specific rate of outbound gossip messages, expressed in bytes per +; second. This setting controls the long-term average speed of gossip traffic +; sent from your node. The rate limit is applied to each peer. If the rate of +; outgoing messages exceeds this value, lnd will start to queue and delay +; messages sending to that peer to stay within the limit. +; gossip.peer-msg-rate-bytes=51200 + [invoices] ; If a hold invoice has accepted htlcs that reach their expiry height and are diff --git a/server.go b/server.go index 8770f7ae5..7238fa2b6 100644 --- a/server.go +++ b/server.go @@ -1103,6 +1103,7 @@ func newServer(ctx context.Context, cfg *Config, listenAddrs []net.Addr, MsgBurstBytes: cfg.Gossip.MsgBurstBytes, FilterConcurrency: cfg.Gossip.FilterConcurrency, BanThreshold: cfg.Gossip.BanThreshold, + PeerMsgRateBytes: cfg.Gossip.PeerMsgRateBytes, }, nodeKeyDesc) accessCfg := &accessManConfig{