From bc6dd8e3aa8a2b567cb792625d5f3d5aa0192269 Mon Sep 17 00:00:00 2001 From: Zsolt Felfoldi Date: Sat, 20 Jan 2018 19:09:18 +0100 Subject: [PATCH 1/4] eth, les, cmd: limit LES connections, add ethpeers flag --- cmd/geth/main.go | 1 + cmd/geth/usage.go | 4 +++- cmd/utils/flags.go | 15 +++++++++++++-- eth/backend.go | 10 +--------- eth/config.go | 4 +++- eth/gen_config.go | 6 ++++++ les/backend.go | 5 ++++- les/handler.go | 8 +++++++- les/helper_test.go | 2 +- les/server.go | 4 +++- node/defaults.go | 2 +- 11 files changed, 43 insertions(+), 18 deletions(-) diff --git a/cmd/geth/main.go b/cmd/geth/main.go index b955bd243e..4865117450 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -85,6 +85,7 @@ var ( utils.FastSyncFlag, utils.LightModeFlag, utils.SyncModeFlag, + utils.EthPeersFlag, utils.LightServFlag, utils.LightPeersFlag, utils.LightKDFFlag, diff --git a/cmd/geth/usage.go b/cmd/geth/usage.go index a834d5b7ae..b8c0042865 100644 --- a/cmd/geth/usage.go +++ b/cmd/geth/usage.go @@ -22,10 +22,11 @@ import ( "io" "sort" + "strings" + "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/internal/debug" "gopkg.in/urfave/cli.v1" - "strings" ) // AppHelpTemplate is the test template for the default, global app help topic. @@ -76,6 +77,7 @@ var AppHelpFlagGroups = []flagGroup{ utils.SyncModeFlag, utils.EthStatsURLFlag, utils.IdentityFlag, + utils.EthPeersFlag, utils.LightServFlag, utils.LightPeersFlag, utils.LightKDFFlag, diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 89dcd230c4..666a325987 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -171,6 +171,11 @@ var ( Value: &defaultSyncMode, } + EthPeersFlag = cli.IntFlag{ + Name: "ethpeers", + Usage: "Maximum number of ETH peers", + Value: 25, + } LightServFlag = cli.IntFlag{ Name: "lightserv", Usage: "Maximum percentage of time allowed for serving LES requests (0-90)", @@ -179,7 +184,7 @@ var ( LightPeersFlag = cli.IntFlag{ Name: "lightpeers", Usage: "Maximum number of LES client peers", - Value: 20, + Value: 100, } LightKDFFlag = cli.BoolFlag{ Name: "lightkdf", @@ -433,7 +438,7 @@ var ( MaxPeersFlag = cli.IntFlag{ Name: "maxpeers", Usage: "Maximum number of network peers (network disabled if set to 0)", - Value: 25, + Value: 125, } MaxPendingPeersFlag = cli.IntFlag{ Name: "maxpendpeers", @@ -791,7 +796,10 @@ func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) { if ctx.GlobalIsSet(MaxPeersFlag.Name) { cfg.MaxPeers = ctx.GlobalInt(MaxPeersFlag.Name) + } else if ctx.GlobalIsSet(EthPeersFlag.Name) || ctx.GlobalIsSet(LightPeersFlag.Name) { + cfg.MaxPeers = ctx.GlobalInt(EthPeersFlag.Name) + ctx.GlobalInt(LightPeersFlag.Name) } + if ctx.GlobalIsSet(MaxPendingPeersFlag.Name) { cfg.MaxPendingPeers = ctx.GlobalInt(MaxPendingPeersFlag.Name) } @@ -989,6 +997,9 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) { case ctx.GlobalBool(LightModeFlag.Name): cfg.SyncMode = downloader.LightSync } + if ctx.GlobalIsSet(EthPeersFlag.Name) { + cfg.EthPeers = ctx.GlobalInt(EthPeersFlag.Name) + } if ctx.GlobalIsSet(LightServFlag.Name) { cfg.LightServ = ctx.GlobalInt(LightServFlag.Name) } diff --git a/eth/backend.go b/eth/backend.go index c39974a2c0..9bf0050343 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -390,16 +390,8 @@ func (s *Ethereum) Start(srvr *p2p.Server) error { // Start the RPC service s.netRPCService = ethapi.NewPublicNetAPI(srvr, s.NetVersion()) - // Figure out a max peers count based on the server limits - maxPeers := srvr.MaxPeers - if s.config.LightServ > 0 { - maxPeers -= s.config.LightPeers - if maxPeers < srvr.MaxPeers/2 { - maxPeers = srvr.MaxPeers / 2 - } - } // Start the networking layer and the light server if requested - s.protocolManager.Start(maxPeers) + s.protocolManager.Start(s.config.EthPeers) if s.lesServer != nil { s.lesServer.Start(srvr) } diff --git a/eth/config.go b/eth/config.go index 4399560fa3..7f2bcda785 100644 --- a/eth/config.go +++ b/eth/config.go @@ -43,7 +43,8 @@ var DefaultConfig = Config{ DatasetsOnDisk: 2, }, NetworkId: 1, - LightPeers: 20, + EthPeers: 25, + LightPeers: 100, DatabaseCache: 128, GasPrice: big.NewInt(18 * params.Shannon), @@ -78,6 +79,7 @@ type Config struct { // Protocol options NetworkId uint64 // Network ID to use for selecting peers to connect to SyncMode downloader.SyncMode + EthPeers int `toml:",omitempty"` // Maximum number of ETH peers // Light client options LightServ int `toml:",omitempty"` // Maximum percentage of time allowed for serving LES requests diff --git a/eth/gen_config.go b/eth/gen_config.go index 4f2e82d941..6da7eaeb61 100644 --- a/eth/gen_config.go +++ b/eth/gen_config.go @@ -20,6 +20,7 @@ func (c Config) MarshalTOML() (interface{}, error) { Genesis *core.Genesis `toml:",omitempty"` NetworkId uint64 SyncMode downloader.SyncMode + EthPeers int `toml:",omitempty"` LightServ int `toml:",omitempty"` LightPeers int `toml:",omitempty"` SkipBcVersionCheck bool `toml:"-"` @@ -39,6 +40,7 @@ func (c Config) MarshalTOML() (interface{}, error) { enc.Genesis = c.Genesis enc.NetworkId = c.NetworkId enc.SyncMode = c.SyncMode + enc.EthPeers = c.EthPeers enc.LightServ = c.LightServ enc.LightPeers = c.LightPeers enc.SkipBcVersionCheck = c.SkipBcVersionCheck @@ -61,6 +63,7 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { Genesis *core.Genesis `toml:",omitempty"` NetworkId *uint64 SyncMode *downloader.SyncMode + EthPeers *int `toml:",omitempty"` LightServ *int `toml:",omitempty"` LightPeers *int `toml:",omitempty"` SkipBcVersionCheck *bool `toml:"-"` @@ -89,6 +92,9 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { if dec.SyncMode != nil { c.SyncMode = *dec.SyncMode } + if dec.EthPeers != nil { + c.EthPeers = *dec.EthPeers + } if dec.LightServ != nil { c.LightServ = *dec.LightServ } diff --git a/les/backend.go b/les/backend.go index 798e44e85c..6a324cb04b 100644 --- a/les/backend.go +++ b/les/backend.go @@ -46,6 +46,8 @@ import ( ) type LightEthereum struct { + config *eth.Config + odr *LesOdr relay *LesTxRelay chainConfig *params.ChainConfig @@ -92,6 +94,7 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) { quitSync := make(chan struct{}) leth := &LightEthereum{ + config: config, chainConfig: chainConfig, chainDb: chainDb, eventMux: ctx.EventMux, @@ -224,7 +227,7 @@ func (s *LightEthereum) Start(srvr *p2p.Server) error { // clients are searching for the first advertised protocol in the list protocolVersion := AdvertiseProtocolVersions[0] s.serverPool.start(srvr, lesTopic(s.blockchain.Genesis().Hash(), protocolVersion)) - s.protocolManager.Start() + s.protocolManager.Start(s.config.LightPeers) return nil } diff --git a/les/handler.go b/les/handler.go index d627c3e184..2abf14466b 100644 --- a/les/handler.go +++ b/les/handler.go @@ -111,6 +111,7 @@ type ProtocolManager struct { downloader *downloader.Downloader fetcher *lightFetcher peers *peerSet + maxPeers int SubProtocols []p2p.Protocol @@ -218,7 +219,9 @@ func (pm *ProtocolManager) removePeer(id string) { pm.peers.Unregister(id) } -func (pm *ProtocolManager) Start() { +func (pm *ProtocolManager) Start(maxPeers int) { + pm.maxPeers = maxPeers + if pm.lightSync { go pm.syncer() } else { @@ -259,6 +262,9 @@ func (pm *ProtocolManager) newPeer(pv int, nv uint64, p *p2p.Peer, rw p2p.MsgRea // handle is the callback invoked to manage the life cycle of a les peer. When // this function terminates, the peer is disconnected. func (pm *ProtocolManager) handle(p *peer) error { + if pm.peers.Len() >= pm.maxPeers { + return p2p.DiscTooManyPeers + } p.Log().Debug("Light Ethereum peer connected", "name", p.Name()) // Execute the LES handshake diff --git a/les/helper_test.go b/les/helper_test.go index b881b41ce8..768389ca35 100644 --- a/les/helper_test.go +++ b/les/helper_test.go @@ -176,7 +176,7 @@ func newTestProtocolManager(lightSync bool, blocks int, generator func(int, *cor srv.fcManager = flowcontrol.NewClientManager(50, 10, 1000000000) srv.fcCostStats = newCostStats(nil) } - pm.Start() + pm.Start(1000) return pm, nil } diff --git a/les/server.go b/les/server.go index ec2e44fecc..85ebbf8988 100644 --- a/les/server.go +++ b/les/server.go @@ -38,6 +38,7 @@ import ( ) type LesServer struct { + config *eth.Config protocolManager *ProtocolManager fcManager *flowcontrol.ClientManager // nil if our node is client only fcCostStats *requestCostStats @@ -62,6 +63,7 @@ func NewLesServer(eth *eth.Ethereum, config *eth.Config) (*LesServer, error) { } srv := &LesServer{ + config: config, protocolManager: pm, quitSync: quitSync, lesTopics: lesTopics, @@ -108,7 +110,7 @@ func (s *LesServer) Protocols() []p2p.Protocol { // Start starts the LES server func (s *LesServer) Start(srvr *p2p.Server) { - s.protocolManager.Start() + s.protocolManager.Start(s.config.LightPeers) for _, topic := range s.lesTopics { topic := topic go func() { diff --git a/node/defaults.go b/node/defaults.go index d4e1486834..da3b3782e8 100644 --- a/node/defaults.go +++ b/node/defaults.go @@ -42,7 +42,7 @@ var DefaultConfig = Config{ WSModules: []string{"net", "web3"}, P2P: p2p.Config{ ListenAddr: ":30303", - MaxPeers: 25, + MaxPeers: 125, NAT: nat.Any(), }, } From 4933496fb260cac29498abcea17dad52f5b7628f Mon Sep 17 00:00:00 2001 From: Zsolt Felfoldi Date: Sun, 21 Jan 2018 22:53:38 +0100 Subject: [PATCH 2/4] cmd/utils: use eth.DefaultConfig for EthPeers and LightPeers --- cmd/utils/flags.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 666a325987..ae4d7e67dd 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -174,7 +174,7 @@ var ( EthPeersFlag = cli.IntFlag{ Name: "ethpeers", Usage: "Maximum number of ETH peers", - Value: 25, + Value: eth.DefaultConfig.EthPeers, } LightServFlag = cli.IntFlag{ Name: "lightserv", @@ -184,7 +184,7 @@ var ( LightPeersFlag = cli.IntFlag{ Name: "lightpeers", Usage: "Maximum number of LES client peers", - Value: 100, + Value: eth.DefaultConfig.LightPeers, } LightKDFFlag = cli.BoolFlag{ Name: "lightkdf", From 7e5f7f0b6e9f7bfc66cbbd50db54b9d47fe77d34 Mon Sep 17 00:00:00 2001 From: Zsolt Felfoldi Date: Tue, 23 Jan 2018 16:12:23 +0100 Subject: [PATCH 3/4] cmd: maxpeers calculation algorithm --- cmd/geth/config.go | 2 +- cmd/utils/flags.go | 79 +++++++++++++++++++++++++++++++++++++--------- 2 files changed, 65 insertions(+), 16 deletions(-) diff --git a/cmd/geth/config.go b/cmd/geth/config.go index 9c703758e0..673b36a306 100644 --- a/cmd/geth/config.go +++ b/cmd/geth/config.go @@ -131,7 +131,7 @@ func makeConfigNode(ctx *cli.Context) (*node.Node, gethConfig) { if err != nil { utils.Fatalf("Failed to create the protocol stack: %v", err) } - utils.SetEthConfig(ctx, stack, &cfg.Eth) + utils.SetEthConfig(ctx, stack, &cfg.Eth, &cfg.Node.P2P) if ctx.GlobalIsSet(utils.EthStatsURLFlag.Name) { cfg.Ethstats.URL = ctx.GlobalString(utils.EthStatsURLFlag.Name) } diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index ae4d7e67dd..f46ea440a2 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -794,23 +794,21 @@ func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) { setBootstrapNodes(ctx, cfg) setBootstrapNodesV5(ctx, cfg) - if ctx.GlobalIsSet(MaxPeersFlag.Name) { - cfg.MaxPeers = ctx.GlobalInt(MaxPeersFlag.Name) - } else if ctx.GlobalIsSet(EthPeersFlag.Name) || ctx.GlobalIsSet(LightPeersFlag.Name) { - cfg.MaxPeers = ctx.GlobalInt(EthPeersFlag.Name) + ctx.GlobalInt(LightPeersFlag.Name) - } - + // note: cfg.MaxPeers is calculated in SetEthConfig if ctx.GlobalIsSet(MaxPendingPeersFlag.Name) { cfg.MaxPendingPeers = ctx.GlobalInt(MaxPendingPeersFlag.Name) } - if ctx.GlobalIsSet(NoDiscoverFlag.Name) || ctx.GlobalBool(LightModeFlag.Name) { + + lightClient := ctx.GlobalBool(LightModeFlag.Name) || ctx.GlobalString(SyncModeFlag.Name) == "light" + lightServer := ctx.GlobalInt(LightServFlag.Name) != 0 + if ctx.GlobalIsSet(NoDiscoverFlag.Name) || lightClient { cfg.NoDiscovery = true } // if we're running a light client or server, force enable the v5 peer discovery // unless it is explicitly disabled with --nodiscover note that explicitly specifying // --v5disc overrides --nodiscover, in which case the later only disables v4 discovery - forceV5Discovery := (ctx.GlobalBool(LightModeFlag.Name) || ctx.GlobalInt(LightServFlag.Name) > 0) && !ctx.GlobalBool(NoDiscoverFlag.Name) + forceV5Discovery := (lightClient || lightServer) && !ctx.GlobalBool(NoDiscoverFlag.Name) if ctx.GlobalIsSet(DiscoveryV5Flag.Name) { cfg.DiscoveryV5 = ctx.GlobalBool(DiscoveryV5Flag.Name) } else if forceV5Discovery { @@ -976,7 +974,7 @@ func SetShhConfig(ctx *cli.Context, stack *node.Node, cfg *whisper.Config) { } // SetEthConfig applies eth-related command line flags to the config. -func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) { +func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config, p2pcfg *p2p.Config) { // Avoid conflicting network flags checkExclusive(ctx, DeveloperFlag, TestnetFlag, RinkebyFlag) checkExclusive(ctx, FastSyncFlag, LightModeFlag, SyncModeFlag) @@ -997,19 +995,70 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) { case ctx.GlobalBool(LightModeFlag.Name): cfg.SyncMode = downloader.LightSync } - if ctx.GlobalIsSet(EthPeersFlag.Name) { - cfg.EthPeers = ctx.GlobalInt(EthPeersFlag.Name) - } if ctx.GlobalIsSet(LightServFlag.Name) { cfg.LightServ = ctx.GlobalInt(LightServFlag.Name) } - if ctx.GlobalIsSet(LightPeersFlag.Name) { - cfg.LightPeers = ctx.GlobalInt(LightPeersFlag.Name) - } if ctx.GlobalIsSet(NetworkIdFlag.Name) { cfg.NetworkId = ctx.GlobalUint64(NetworkIdFlag.Name) } + ethPeers := cfg.EthPeers + if ctx.GlobalIsSet(EthPeersFlag.Name) { + ethPeers = ctx.GlobalInt(EthPeersFlag.Name) + } + ethPeersFixed := ctx.GlobalIsSet(EthPeersFlag.Name) + lightPeers := cfg.LightPeers + if ctx.GlobalIsSet(LightPeersFlag.Name) { + lightPeers = ctx.GlobalInt(LightPeersFlag.Name) + } + lightPeersFixed := ctx.GlobalIsSet(LightPeersFlag.Name) + + if cfg.SyncMode == downloader.LightSync { + // ETH is not used + ethPeers = 0 + ethPeersFixed = true + } else if cfg.LightServ == 0 { + // LES is not used + lightPeers = 0 + lightPeersFixed = true + } + + // if maxpeers is specified, adjust ethpeers and/or lightpeers if possible + if ctx.GlobalIsSet(MaxPeersFlag.Name) { + maxPeersDiff := ctx.GlobalInt(MaxPeersFlag.Name) - ethPeers - lightPeers + if maxPeersDiff > 0 { + // when adjusting upwards, ETH has priority + if !ethPeersFixed { + ethPeers += maxPeersDiff + } else if !lightPeersFixed { + lightPeers += maxPeersDiff + } + } else if maxPeersDiff < 0 { + // when adjusting downwards, LES has priority + if !lightPeersFixed { + if lightPeers >= -maxPeersDiff { + lightPeers += maxPeersDiff + maxPeersDiff = 0 + } else { + maxPeersDiff += lightPeers + lightPeers = 0 + } + } + if !ethPeersFixed { + if ethPeers >= -maxPeersDiff { + ethPeers += maxPeersDiff + maxPeersDiff = 0 + } else { + maxPeersDiff += ethPeers + ethPeers = 0 + } + } + } + } + cfg.EthPeers = ethPeers + cfg.LightPeers = lightPeers + p2pcfg.MaxPeers = ethPeers + lightPeers + if ctx.GlobalIsSet(CacheFlag.Name) { cfg.DatabaseCache = ctx.GlobalInt(CacheFlag.Name) } From 7c62c6772c306e7d48bc542254dd1c7443fab71d Mon Sep 17 00:00:00 2001 From: Zsolt Felfoldi Date: Fri, 26 Jan 2018 11:09:02 +0100 Subject: [PATCH 4/4] cmd/utils: print log message with max peer count --- cmd/utils/flags.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index f46ea440a2..212e5d2a92 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -1059,6 +1059,8 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config, p2pcfg *p cfg.LightPeers = lightPeers p2pcfg.MaxPeers = ethPeers + lightPeers + log.Info("Maximum peer count", "ETH", cfg.EthPeers, "LES", cfg.LightPeers, "total", p2pcfg.MaxPeers) + if ctx.GlobalIsSet(CacheFlag.Name) { cfg.DatabaseCache = ctx.GlobalInt(CacheFlag.Name) }