diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 333d54b514..3cecd61d11 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -142,6 +142,7 @@ var ( utils.NodeKeyFileFlag, utils.NodeKeyHexFlag, utils.DNSDiscoveryFlag, + utils.EthProtocolsFlag, utils.DeveloperFlag, utils.DeveloperPeriodFlag, utils.ClassicFlag, diff --git a/cmd/geth/misccmd.go b/cmd/geth/misccmd.go index 4dcb299716..97e4fe806a 100644 --- a/cmd/geth/misccmd.go +++ b/cmd/geth/misccmd.go @@ -132,7 +132,7 @@ func version(ctx *cli.Context) error { fmt.Println("Git Commit Date:", gitDate) } fmt.Println("Architecture:", runtime.GOARCH) - fmt.Println("Protocol Versions:", eth.ProtocolVersions) + fmt.Println("Protocol Versions:", eth.DefaultProtocolVersions) fmt.Println("Go Version:", runtime.Version()) fmt.Println("Operating System:", runtime.GOOS) fmt.Printf("GOPATH=%s\n", os.Getenv("GOPATH")) diff --git a/cmd/geth/usage.go b/cmd/geth/usage.go index 9703463d7d..6506b6e30c 100644 --- a/cmd/geth/usage.go +++ b/cmd/geth/usage.go @@ -167,6 +167,7 @@ var AppHelpFlagGroups = []flags.FlagGroup{ utils.LegacyBootnodesV4Flag, utils.LegacyBootnodesV5Flag, utils.DNSDiscoveryFlag, + utils.EthProtocolsFlag, utils.ListenPortFlag, utils.MaxPeersFlag, utils.MaxPendingPeersFlag, diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 60ea2d4d70..98996fd7fe 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -141,6 +141,11 @@ var ( Usage: "Explicitly set network id (integer)(For testnets: use --ropsten, --rinkeby, --goerli, --kotti, --mordor, --yolov1 instead)", Value: eth.DefaultConfig.NetworkId, } + EthProtocolsFlag = cli.StringFlag{ + Name: "eth.protocols", + Usage: "Sets the Ethereum Protocol versions (65|64|63) (default = 65,64,63 first is primary)", + Value: "", + } ClassicFlag = cli.BoolFlag{ Name: "classic", Usage: "Ethereum Classic network: pre-configured Ethereum Classic mainnet", @@ -1726,6 +1731,44 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) { cfg.NetworkId = *cfg.Genesis.GetNetworkID() } + if ctx.GlobalIsSet(EthProtocolsFlag.Name) { + protocolVersions := SplitAndTrim(ctx.GlobalString(EthProtocolsFlag.Name)) + if len(protocolVersions) == 0 { + Fatalf("--%s must be comma separated list of %s", EthProtocolsFlag.Name, strings.Join(strings.Fields(fmt.Sprint(eth.DefaultProtocolVersions)), ",")) + } + + seenVersions := map[uint]interface{}{} + for _, versionString := range protocolVersions { + version, err := strconv.ParseUint(versionString, 10, 0) + if err != nil { + Fatalf("--%s has invalid value \"%v\" with error: %v", EthProtocolsFlag.Name, versionString, err) + } + + if _, duplicate := seenVersions[uint(version)]; duplicate { + Fatalf("--%s has duplicate version of %v", EthProtocolsFlag.Name, versionString) + } + + isValid := false + for _, proto := range eth.DefaultProtocolVersions { + if proto == uint(version) { + isValid = true + seenVersions[uint(version)] = nil + break + } + } + + if !isValid { + Fatalf("--%s must be comma separated list of %s", EthProtocolsFlag.Name, strings.Join(strings.Fields(fmt.Sprint(eth.DefaultProtocolVersions)), ",")) + } + cfg.ProtocolVersions = append(cfg.ProtocolVersions, uint(version)) + } + } + + // set default protocol versions + if len(cfg.ProtocolVersions) == 0 { + cfg.ProtocolVersions = eth.DefaultProtocolVersions + } + // Set DNS discovery defaults for hard coded networks with DNS defaults. switch { case ctx.GlobalBool(LegacyTestnetFlag.Name) || ctx.GlobalBool(RopstenFlag.Name): diff --git a/eth/backend.go b/eth/backend.go index f253c3aad6..284f938565 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -157,7 +157,7 @@ func New(stack *node.Node, config *Config) (*Ethereum, error) { if bcVersion != nil { dbVer = fmt.Sprintf("%d", *bcVersion) } - log.Info("Initialising Ethereum protocol", "versions", ProtocolVersions, "network", config.NetworkId, "dbversion", dbVer) + log.Info("Initialising Ethereum protocol", "versions", config.ProtocolVersions, "network", config.NetworkId, "dbversion", dbVer) if !config.SkipBcVersionCheck { if bcVersion != nil && *bcVersion > core.BlockChainVersion { @@ -514,7 +514,7 @@ func (s *Ethereum) EventMux() *event.TypeMux { return s.eventMux } func (s *Ethereum) Engine() consensus.Engine { return s.engine } func (s *Ethereum) ChainDb() ethdb.Database { return s.chainDb } func (s *Ethereum) IsListening() bool { return true } // Always listening -func (s *Ethereum) EthVersion() int { return int(ProtocolVersions[0]) } +func (s *Ethereum) EthVersion() int { return int(s.config.ProtocolVersions[0]) } func (s *Ethereum) NetVersion() uint64 { return s.networkID } func (s *Ethereum) Downloader() *downloader.Downloader { return s.protocolManager.downloader } func (s *Ethereum) Synced() bool { return atomic.LoadUint32(&s.protocolManager.acceptTxs) == 1 } @@ -524,8 +524,8 @@ func (s *Ethereum) BloomIndexer() *core.ChainIndexer { return s.bloomIndexer } // Protocols returns all the currently configured // network protocols to start. func (s *Ethereum) Protocols() []p2p.Protocol { - protos := make([]p2p.Protocol, len(ProtocolVersions)) - for i, vsn := range ProtocolVersions { + protos := make([]p2p.Protocol, len(s.config.ProtocolVersions)) + for i, vsn := range s.config.ProtocolVersions { protos[i] = s.protocolManager.makeProtocol(vsn) protos[i].Attributes = []enr.Entry{s.currentEthEntry()} protos[i].DialCandidates = s.dialCandidates diff --git a/eth/config.go b/eth/config.go index 9e5cef305c..f71e279d9f 100644 --- a/eth/config.go +++ b/eth/config.go @@ -112,8 +112,9 @@ type Config struct { Genesis *genesisT.Genesis `toml:",omitempty"` // Protocol options - NetworkId uint64 // Network ID to use for selecting peers to connect to - SyncMode downloader.SyncMode + NetworkId uint64 // Network ID to use for selecting peers to connect to + ProtocolVersions []uint // Protocol versions are the supported versions of the eth protocol (first is primary). + SyncMode downloader.SyncMode // This can be set to list of enrtree:// URLs which will be queried for // for nodes to connect to. diff --git a/eth/protocol.go b/eth/protocol.go index dc75d6b31a..ff38da3df0 100644 --- a/eth/protocol.go +++ b/eth/protocol.go @@ -39,8 +39,8 @@ const ( // protocolName is the official short name of the protocol used during capability negotiation. const protocolName = "eth" -// ProtocolVersions are the supported versions of the eth protocol (first is primary). -var ProtocolVersions = []uint{eth65, eth64, eth63} +// DefaultProtocolVersions are the supported versions of the eth protocol (first is primary). +var DefaultProtocolVersions = []uint{eth65, eth64, eth63} // protocolLengths are the number of implemented message corresponding to different protocol versions. var protocolLengths = map[uint]uint64{eth65: 17, eth64: 17, eth63: 17} diff --git a/ethstats/ethstats.go b/ethstats/ethstats.go index eb21595bfe..f82cffab1f 100644 --- a/ethstats/ethstats.go +++ b/ethstats/ethstats.go @@ -61,6 +61,7 @@ const ( // backend encompasses the bare-minimum functionality needed for ethstats reporting type backend interface { + ProtocolVersion() int SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription CurrentHeader() *types.Header @@ -468,7 +469,7 @@ func (s *Service) login(conn *connWrapper) error { var network, protocol string if info := infos.Protocols["eth"]; info != nil { network = fmt.Sprintf("%d", info.(*eth.NodeInfo).Network) - protocol = fmt.Sprintf("eth/%d", eth.ProtocolVersions[0]) + protocol = fmt.Sprintf("eth/%d", s.backend.ProtocolVersion()) } else { network = fmt.Sprintf("%d", infos.Protocols["les"].(*les.NodeInfo).Network) protocol = fmt.Sprintf("les/%d", les.ClientProtocolVersions[0])