diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 02443d99a6..91426fdb21 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -143,6 +143,7 @@ var ( utils.NoDiscoverFlag, utils.DiscoveryV4Flag, utils.DiscoveryV5Flag, + utils.InstanceFlag, utils.LegacyDiscoveryV5Flag, // deprecated utils.NetrestrictFlag, utils.NodeKeyFileFlag, diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index b20c468d04..b8ccfb4f97 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -150,6 +150,12 @@ var ( Usage: "Minimum free disk space in MB, once reached triggers auto shut down (default = --cache.gc converted to MB, 0 = disabled)", Category: flags.EthCategory, } + InstanceFlag = &cli.IntFlag{ + Name: "instance", + Usage: "Configures the ports to avoid conflicts when running multiple nodes on the same machine. Maximum is 200. Only applicable for: port, authrpc.port, discovery,port, http.port, ws.port", + Value: 1, + Category: flags.EthCategory, + } KeyStoreDirFlag = &flags.DirectoryFlag{ Name: "keystore", Usage: "Directory for the keystore (default = inside the datadir)", @@ -1537,6 +1543,7 @@ func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) { // SetNodeConfig applies node-related command line flags to the config. func SetNodeConfig(ctx *cli.Context, cfg *node.Config) { + setInstance(ctx, cfg) SetP2PConfig(ctx, &cfg.P2P) setIPC(ctx, cfg) setHTTP(ctx, cfg) @@ -2531,3 +2538,24 @@ func ParseCLIAndConfigStateScheme(cliScheme, cfgScheme string) (string, error) { } return "", fmt.Errorf("incompatible state scheme, CLI: %s, config: %s", cliScheme, cfgScheme) } + +// setInstance configures the port numbers for the given instance. +func setInstance(ctx *cli.Context, cfg *node.Config) { + if ctx.IsSet(InstanceFlag.Name) { + cfg.Instance = ctx.Int(InstanceFlag.Name) + } + + if cfg.Instance > 200 { + Fatalf("Instance number %d is too high, maximum is 200", cfg.Instance) + } + + if cfg.Instance == 1 { // using default ports + return + } + + cfg.AuthPort = node.DefaultConfig.AuthPort + cfg.Instance*100 - 100 + cfg.HTTPPort = node.DefaultHTTPPort - cfg.Instance + 1 + cfg.WSPort = node.DefaultWSPort + cfg.Instance*2 - 2 + cfg.P2P.ListenAddr = fmt.Sprintf(":%d", node.DefaultListenPort+cfg.Instance-1) + cfg.P2P.DiscAddr = fmt.Sprintf(":%d", node.DefaultDiscPort+cfg.Instance-1) +} diff --git a/node/config.go b/node/config.go index bc30a0ab0a..a3dcd3c9f8 100644 --- a/node/config.go +++ b/node/config.go @@ -239,6 +239,8 @@ type Config struct { EnablePersonal bool `toml:"-"` DBEngine string `toml:",omitempty"` + + Instance int `toml:",omitempty"` } // IPCEndpoint resolves an IPC endpoint based on a configured value, taking into diff --git a/node/defaults.go b/node/defaults.go index 41497a2e0d..2defed7215 100644 --- a/node/defaults.go +++ b/node/defaults.go @@ -28,12 +28,14 @@ import ( ) const ( - DefaultHTTPHost = "localhost" // Default host interface for the HTTP RPC server - DefaultHTTPPort = 8545 // Default TCP port for the HTTP RPC server - DefaultWSHost = "localhost" // Default host interface for the websocket RPC server - DefaultWSPort = 8546 // Default TCP port for the websocket RPC server - DefaultAuthHost = "localhost" // Default host interface for the authenticated apis - DefaultAuthPort = 8551 // Default port for the authenticated apis + DefaultHTTPHost = "localhost" // Default host interface for the HTTP RPC server + DefaultHTTPPort = 8545 // Default TCP port for the HTTP RPC server + DefaultWSHost = "localhost" // Default host interface for the websocket RPC server + DefaultWSPort = 8546 // Default TCP port for the websocket RPC server + DefaultAuthHost = "localhost" // Default host interface for the authenticated apis + DefaultAuthPort = 8551 // Default port for the authenticated apis + DefaultListenPort = 30303 // Default port for the TCP listening address + DefaultDiscPort = 30303 // Default port for the UDP discovery address ) const ( @@ -74,6 +76,7 @@ var DefaultConfig = Config{ NAT: nat.Any(), }, DBEngine: "", // Use whatever exists, will default to Pebble if non-existent and supported + Instance: 1, } // DefaultDataDir is the default data directory to use for the databases and other