diff --git a/config/config.go b/config/config.go index 2b3b7f1cc..acaf188b4 100644 --- a/config/config.go +++ b/config/config.go @@ -72,6 +72,7 @@ type ( DialTimeout time.Duration `yaml:"DialTimeout"` ProtoTickInterval time.Duration `yaml:"ProtoTickInterval"` MaxPeers int `yaml:"MaxPeers"` + AttemptConnPeers int `yaml:"AttemptConnPeers"` MinPeers int `yaml:"MinPeers"` Monitoring metrics.PrometheusConfig `yaml:"Monitoring"` RPC RPCConfig `yaml:"RPC"` diff --git a/config/protocol.mainnet.yml b/config/protocol.mainnet.yml index 51db3ecdd..ba284513a 100644 --- a/config/protocol.mainnet.yml +++ b/config/protocol.mainnet.yml @@ -46,7 +46,8 @@ ApplicationConfiguration: Relay: true DialTimeout: 3 ProtoTickInterval: 2 - MaxPeers: 50 + MaxPeers: 100 + AttemptConnPeers: 20 MinPeers: 5 RPC: Enabled: true diff --git a/config/protocol.privnet.docker.four.yml b/config/protocol.privnet.docker.four.yml index 18b05e8c8..40b7e0437 100644 --- a/config/protocol.privnet.docker.four.yml +++ b/config/protocol.privnet.docker.four.yml @@ -34,7 +34,8 @@ ApplicationConfiguration: Relay: true DialTimeout: 3 ProtoTickInterval: 2 - MaxPeers: 50 + MaxPeers: 10 + AttemptConnPeers: 5 MinPeers: 3 RPC: Enabled: true diff --git a/config/protocol.privnet.docker.one.yml b/config/protocol.privnet.docker.one.yml index 2d628984e..bee278bff 100644 --- a/config/protocol.privnet.docker.one.yml +++ b/config/protocol.privnet.docker.one.yml @@ -31,7 +31,8 @@ ApplicationConfiguration: Relay: true DialTimeout: 3 ProtoTickInterval: 2 - MaxPeers: 50 + MaxPeers: 10 + AttemptConnPeers: 5 MinPeers: 3 RPC: Enabled: true diff --git a/config/protocol.privnet.docker.three.yml b/config/protocol.privnet.docker.three.yml index 6894ba952..21c214ea6 100644 --- a/config/protocol.privnet.docker.three.yml +++ b/config/protocol.privnet.docker.three.yml @@ -31,7 +31,8 @@ ApplicationConfiguration: Relay: true DialTimeout: 3 ProtoTickInterval: 2 - MaxPeers: 50 + MaxPeers: 10 + AttemptConnPeers: 5 MinPeers: 3 RPC: Enabled: true diff --git a/config/protocol.privnet.docker.two.yml b/config/protocol.privnet.docker.two.yml index e58dc0c00..546f94f27 100644 --- a/config/protocol.privnet.docker.two.yml +++ b/config/protocol.privnet.docker.two.yml @@ -31,7 +31,8 @@ ApplicationConfiguration: Relay: true DialTimeout: 3 ProtoTickInterval: 2 - MaxPeers: 50 + MaxPeers: 10 + AttemptConnPeers: 5 MinPeers: 3 RPC: Enabled: true diff --git a/config/protocol.privnet.yml b/config/protocol.privnet.yml index 9b039d375..696739465 100644 --- a/config/protocol.privnet.yml +++ b/config/protocol.privnet.yml @@ -37,7 +37,8 @@ ApplicationConfiguration: Relay: true DialTimeout: 3 ProtoTickInterval: 2 - MaxPeers: 50 + MaxPeers: 10 + AttemptConnPeers: 5 MinPeers: 3 RPC: Enabled: true diff --git a/config/protocol.testnet.yml b/config/protocol.testnet.yml index 44fa60e20..f3de694ec 100644 --- a/config/protocol.testnet.yml +++ b/config/protocol.testnet.yml @@ -46,7 +46,8 @@ ApplicationConfiguration: Relay: true DialTimeout: 3 ProtoTickInterval: 2 - MaxPeers: 50 + MaxPeers: 100 + AttemptConnPeers: 20 MinPeers: 5 RPC: Enabled: true diff --git a/config/protocol.unit_testnet.yml b/config/protocol.unit_testnet.yml index 18c50732f..709c52f26 100644 --- a/config/protocol.unit_testnet.yml +++ b/config/protocol.unit_testnet.yml @@ -37,6 +37,7 @@ ApplicationConfiguration: DialTimeout: 3 ProtoTickInterval: 2 MaxPeers: 50 + AttemptConnPeers: 5 MinPeers: 1 RPC: Enabled: true diff --git a/pkg/network/server.go b/pkg/network/server.go index 10b9f6e43..f66145a6c 100644 --- a/pkg/network/server.go +++ b/pkg/network/server.go @@ -18,11 +18,12 @@ import ( const ( // peer numbers are arbitrary at the moment. - defaultMinPeers = 5 - maxPeers = 20 - maxBlockBatch = 200 - maxAddrsToSend = 200 - minPoolCount = 30 + defaultMinPeers = 5 + defaultAttemptConnPeers = 20 + defaultMaxPeers = 100 + maxBlockBatch = 200 + maxAddrsToSend = 200 + minPoolCount = 30 ) var ( @@ -30,6 +31,7 @@ var ( errIdenticalID = errors.New("identical node id") errInvalidHandshake = errors.New("invalid handshake") errInvalidNetwork = errors.New("invalid network") + errMaxPeers = errors.New("max peers reached") errServerShutdown = errors.New("server shutdown") errInvalidInvType = errors.New("invalid inventory type") ) @@ -86,6 +88,22 @@ func NewServer(config ServerConfig, chain core.Blockchainer) *Server { s.MinPeers = defaultMinPeers } + if s.MaxPeers <= 0 { + log.WithFields(log.Fields{ + "MaxPeers configured": s.MaxPeers, + "MaxPeers actual": defaultMaxPeers, + }).Info("bad MaxPeers configured, using the default value") + s.MaxPeers = defaultMaxPeers + } + + if s.AttemptConnPeers <= 0 { + log.WithFields(log.Fields{ + "AttemptConnPeers configured": s.AttemptConnPeers, + "AttemptConnPeers actual": defaultAttemptConnPeers, + }).Info("bad AttemptConnPeers configured, using the default value") + s.AttemptConnPeers = defaultAttemptConnPeers + } + s.transport = NewTCPTransport(s, fmt.Sprintf(":%d", config.ListenTCP)) s.discovery = NewDefaultDiscovery( s.DialTimeout, @@ -137,9 +155,8 @@ func (s *Server) BadPeers() []string { func (s *Server) run() { for { - c := s.PeerCount() - if c < s.ServerConfig.MinPeers { - s.discovery.RequestRemote(maxPeers - c) + if s.PeerCount() < s.MinPeers { + s.discovery.RequestRemote(s.AttemptConnPeers) } if s.discovery.PoolCount() < minPoolCount { select { @@ -170,6 +187,16 @@ func (s *Server) run() { log.WithFields(log.Fields{ "addr": p.RemoteAddr(), }).Info("new peer connected") + peerCount := s.PeerCount() + if peerCount > s.MaxPeers { + s.lock.RLock() + // Pick a random peer and drop connection to it. + for peer := range s.peers { + peer.Disconnect(errMaxPeers) + break + } + s.lock.RUnlock() + } updatePeersConnectedMetric(s.PeerCount()) case drop := <-s.unregister: diff --git a/pkg/network/server_config.go b/pkg/network/server_config.go index 797b45b82..b0e4332eb 100644 --- a/pkg/network/server_config.go +++ b/pkg/network/server_config.go @@ -15,6 +15,11 @@ type ( // connect with some new ones. MinPeers int + // AttemptConnPeers it the number of connection to try to + // establish when the connection count drops below the MinPeers + // value. + AttemptConnPeers int + // MaxPeers it the maximum numbers of peers that can // be connected to the server. MaxPeers int @@ -64,6 +69,7 @@ func NewServerConfig(cfg config.Config) ServerConfig { DialTimeout: appConfig.DialTimeout * time.Second, ProtoTickInterval: appConfig.ProtoTickInterval * time.Second, MaxPeers: appConfig.MaxPeers, + AttemptConnPeers: appConfig.AttemptConnPeers, MinPeers: appConfig.MinPeers, } }