From b61f48e5aad9cf897f5655a0db002a3349109c67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Szil=C3=A1gyi?= Date: Wed, 9 Nov 2016 16:35:04 +0200 Subject: [PATCH] cmd, mobile, node, p2p: surface the discovery V5 bootnodes --- cmd/utils/bootnodes.go | 9 +++++++++ cmd/utils/flags.go | 29 +++++++++++++++++++++++++++-- mobile/discover.go | 34 ++++++++++------------------------ mobile/geth.go | 26 +++++++++++++++----------- node/config.go | 14 +++++++++++--- node/node.go | 31 ++++++++++++++++--------------- p2p/discv5/net.go | 8 -------- p2p/server.go | 18 +++++++++++++----- 8 files changed, 101 insertions(+), 68 deletions(-) diff --git a/cmd/utils/bootnodes.go b/cmd/utils/bootnodes.go index 1947030fc4..50b6584678 100644 --- a/cmd/utils/bootnodes.go +++ b/cmd/utils/bootnodes.go @@ -19,6 +19,7 @@ package utils import ( "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/p2p/discover" + "github.com/ethereum/go-ethereum/p2p/discv5" "github.com/ethereum/go-ethereum/params" ) @@ -44,6 +45,14 @@ var TestnetBootnodes = []*discover.Node{ // ETH/DEV Cpp Bootnodes } +// DiscoveryV5Bootnodes are the enode URLs of the P2P bootstrap nodes for the +// experimental RLPx v5 topic-discovery network. +var DiscoveryV5Bootnodes = []*discv5.Node{ + discv5.MustParseNode("enode://0cc5f5ffb5d9098c8b8c62325f3797f56509bff942704687b6530992ac706e2cb946b90a34f1f19548cd3c7baccbcaea354531e5983c7d1bc0dee16ce4b6440b@40.118.3.223:30305"), + discv5.MustParseNode("enode://1c7a64d76c0334b0418c004af2f67c50e36a3be60b5e4790bdac0439d21603469a85fad36f2473c9a80eb043ae60936df905fa28f1ff614c3e5dc34f15dcd2dc@40.118.3.223:30308"), + discv5.MustParseNode("enode://85c85d7143ae8bb96924f2b54f1b3e70d8c4d367af305325d30a61385a432f247d2c75c45c6b4a60335060d072d7f5b35dd1d4c45f76941f62a4f83b6e75daaf@40.118.3.223:30309"), +} + // MainnetChainConfig is the chain parameters to run a node on the main network. var MainnetChainConfig = &core.ChainConfig{ HomesteadBlock: params.MainNetHomesteadBlock, diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index a0b305d4a6..0b18d9f794 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -46,6 +46,7 @@ import ( "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/p2p/discover" + "github.com/ethereum/go-ethereum/p2p/discv5" "github.com/ethereum/go-ethereum/p2p/nat" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/pow" @@ -505,13 +506,36 @@ func MakeBootstrapNodes(ctx *cli.Context) []*discover.Node { return bootnodes } +// MakeBootstrapNodesV5 creates a list of bootstrap nodes from the command line +// flags, reverting to pre-configured ones if none have been specified. +func MakeBootstrapNodesV5(ctx *cli.Context) []*discv5.Node { + // Return pre-configured nodes if none were manually requested + if !ctx.GlobalIsSet(BootnodesFlag.Name) { + return DiscoveryV5Bootnodes + } + // Otherwise parse and use the CLI bootstrap nodes + bootnodes := []*discv5.Node{} + + for _, url := range strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",") { + node, err := discv5.ParseNode(url) + if err != nil { + glog.V(logger.Error).Infof("Bootstrap URL %s: %v\n", url, err) + continue + } + bootnodes = append(bootnodes, node) + } + return bootnodes +} + // MakeListenAddress creates a TCP listening address string from set command // line flags. func MakeListenAddress(ctx *cli.Context) string { return fmt.Sprintf(":%d", ctx.GlobalInt(ListenPortFlag.Name)) } -func MakeListenAddressV5(ctx *cli.Context) string { +// MakeDiscoveryV5Address creates a UDP listening address string from set command +// line flags for the V5 discovery protocol. +func MakeDiscoveryV5Address(ctx *cli.Context) string { return fmt.Sprintf(":%d", ctx.GlobalInt(ListenPortFlag.Name)+1) } @@ -647,9 +671,10 @@ func MakeNode(ctx *cli.Context, name, gitCommit string) *node.Node { UserIdent: makeNodeUserIdent(ctx), NoDiscovery: ctx.GlobalBool(NoDiscoverFlag.Name) || ctx.GlobalBool(LightModeFlag.Name), DiscoveryV5: ctx.GlobalBool(DiscoveryV5Flag.Name) || ctx.GlobalBool(LightModeFlag.Name) || ctx.GlobalInt(LightServFlag.Name) > 0, + DiscoveryV5Addr: MakeDiscoveryV5Address(ctx), BootstrapNodes: MakeBootstrapNodes(ctx), + BootstrapNodesV5: MakeBootstrapNodesV5(ctx), ListenAddr: MakeListenAddress(ctx), - ListenAddrV5: MakeListenAddressV5(ctx), NAT: MakeNAT(ctx), MaxPeers: ctx.GlobalInt(MaxPeersFlag.Name), MaxPendingPeers: ctx.GlobalInt(MaxPendingPeersFlag.Name), diff --git a/mobile/discover.go b/mobile/discover.go index 9b221a874e..bb421fc87a 100644 --- a/mobile/discover.go +++ b/mobile/discover.go @@ -23,28 +23,14 @@ import ( "errors" "github.com/ethereum/go-ethereum/cmd/utils" - "github.com/ethereum/go-ethereum/p2p/discover" + "github.com/ethereum/go-ethereum/p2p/discv5" ) -// MainnetBootnodes returns the enode URLs of the P2P bootstrap nodes running -// on the main network. -// -// Note, this needs to be a method to prevent gomobile generating a setter for it. -func MainnetBootnodes() *Enodes { - nodes := &Enodes{nodes: make([]*discover.Node, len(utils.MainnetBootnodes))} - for i, node := range utils.MainnetBootnodes { - nodes.nodes[i] = node - } - return nodes -} - -// TestnetBootnodes returns the enode URLs of the P2P bootstrap nodes running -// on the test network. -// -// Note, this needs to be a method to prevent gomobile generating a setter for it. -func TestnetBootnodes() *Enodes { - nodes := &Enodes{nodes: make([]*discover.Node, len(utils.TestnetBootnodes))} - for i, node := range utils.TestnetBootnodes { +// FoundationBootnodes returns the enode URLs of the P2P bootstrap nodes operated +// by the foundation running the V5 discovery protocol. +func FoundationBootnodes() *Enodes { + nodes := &Enodes{nodes: make([]*discv5.Node, len(utils.DiscoveryV5Bootnodes))} + for i, node := range utils.DiscoveryV5Bootnodes { nodes.nodes[i] = node } return nodes @@ -52,7 +38,7 @@ func TestnetBootnodes() *Enodes { // Enode represents a host on the network. type Enode struct { - node *discover.Node + node *discv5.Node } // NewEnode parses a node designator. @@ -79,7 +65,7 @@ type Enode struct { // // enode://@10.3.58.6:30303?discport=30301 func NewEnode(rawurl string) (*Enode, error) { - node, err := discover.ParseNode(rawurl) + node, err := discv5.ParseNode(rawurl) if err != nil { return nil, err } @@ -87,12 +73,12 @@ func NewEnode(rawurl string) (*Enode, error) { } // Enodes represents a slice of accounts. -type Enodes struct{ nodes []*discover.Node } +type Enodes struct{ nodes []*discv5.Node } // NewEnodes creates a slice of uninitialized enodes. func NewEnodes(size int) *Enodes { return &Enodes{ - nodes: make([]*discover.Node, size), + nodes: make([]*discv5.Node, size), } } diff --git a/mobile/geth.go b/mobile/geth.go index 85ac7fec5d..4d1f48ec3d 100644 --- a/mobile/geth.go +++ b/mobile/geth.go @@ -78,11 +78,11 @@ type NodeConfig struct { // defaultNodeConfig contains the default node configuration values to use if all // or some fields are missing from the user's specified list. var defaultNodeConfig = &NodeConfig{ - BootstrapNodes: MainnetBootnodes(), + BootstrapNodes: FoundationBootnodes(), MaxPeers: 25, EthereumEnabled: true, EthereumNetworkID: 1, - EthereumChainConfig: MainnetChainConfig, + EthereumChainConfig: MainnetChainConfig(), EthereumDatabaseCache: 16, } @@ -106,17 +106,21 @@ func NewNode(datadir string, config *NodeConfig) (*Node, error) { if config.MaxPeers == 0 { config.MaxPeers = defaultNodeConfig.MaxPeers } + if config.BootstrapNodes == nil || config.BootstrapNodes.Size() == 0 { + config.BootstrapNodes = defaultNodeConfig.BootstrapNodes + } // Create the empty networking stack nodeConf := &node.Config{ - Name: clientIdentifier, - DataDir: datadir, - KeyStoreDir: filepath.Join(datadir, "keystore"), // Mobile should never use internal keystores! - NoDiscovery: true, - DiscoveryV5: true, - BootstrapNodes: config.BootstrapNodes.nodes, - ListenAddr: ":0", - NAT: nat.Any(), - MaxPeers: config.MaxPeers, + Name: clientIdentifier, + DataDir: datadir, + KeyStoreDir: filepath.Join(datadir, "keystore"), // Mobile should never use internal keystores! + NoDiscovery: true, + DiscoveryV5: true, + DiscoveryV5Addr: ":0", + BootstrapNodesV5: config.BootstrapNodes.nodes, + ListenAddr: ":0", + NAT: nat.Any(), + MaxPeers: config.MaxPeers, } stack, err := node.New(nodeConf) if err != nil { diff --git a/node/config.go b/node/config.go index dbefcb8a56..62655f2370 100644 --- a/node/config.go +++ b/node/config.go @@ -32,6 +32,7 @@ import ( "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/p2p/discover" + "github.com/ethereum/go-ethereum/p2p/discv5" "github.com/ethereum/go-ethereum/p2p/nat" ) @@ -95,16 +96,23 @@ type Config struct { // or not. Disabling is usually useful for protocol debugging (manual topology). NoDiscovery bool + // DiscoveryV5 specifies whether the the new topic-discovery based V5 discovery + // protocol should be started or not. DiscoveryV5 bool - // Bootstrap nodes used to establish connectivity with the rest of the network. + // Listener address for the V5 discovery protocol UDP traffic. + DiscoveryV5Addr string + + // BootstrapNodes used to establish connectivity with the rest of the network. BootstrapNodes []*discover.Node + // BootstrapNodesV5 used to establish connectivity with the rest of the network + // using the V5 discovery protocol. + BootstrapNodesV5 []*discv5.Node + // Network interface address on which the node should listen for inbound peers. ListenAddr string - ListenAddrV5 string - // If set to a non-nil value, the given NAT port mapper is used to make the // listening port available to the Internet. NAT nat.Interface diff --git a/node/node.go b/node/node.go index fb11696faa..d49ae3a457 100644 --- a/node/node.go +++ b/node/node.go @@ -154,21 +154,22 @@ func (n *Node) Start() error { // Initialize the p2p server. This creates the node key and // discovery databases. n.serverConfig = p2p.Config{ - PrivateKey: n.config.NodeKey(), - Name: n.config.NodeName(), - Discovery: !n.config.NoDiscovery, - DiscoveryV5: n.config.DiscoveryV5, - BootstrapNodes: n.config.BootstrapNodes, - StaticNodes: n.config.StaticNodes(), - TrustedNodes: n.config.TrusterNodes(), - NodeDatabase: n.config.NodeDB(), - ListenAddr: n.config.ListenAddr, - ListenAddrV5: n.config.ListenAddrV5, - NAT: n.config.NAT, - Dialer: n.config.Dialer, - NoDial: n.config.NoDial, - MaxPeers: n.config.MaxPeers, - MaxPendingPeers: n.config.MaxPendingPeers, + PrivateKey: n.config.NodeKey(), + Name: n.config.NodeName(), + Discovery: !n.config.NoDiscovery, + DiscoveryV5: n.config.DiscoveryV5, + DiscoveryV5Addr: n.config.DiscoveryV5Addr, + BootstrapNodes: n.config.BootstrapNodes, + BootstrapNodesV5: n.config.BootstrapNodesV5, + StaticNodes: n.config.StaticNodes(), + TrustedNodes: n.config.TrusterNodes(), + NodeDatabase: n.config.NodeDB(), + ListenAddr: n.config.ListenAddr, + NAT: n.config.NAT, + Dialer: n.config.Dialer, + NoDial: n.config.NoDial, + MaxPeers: n.config.MaxPeers, + MaxPendingPeers: n.config.MaxPendingPeers, } running := &p2p.Server{Config: n.serverConfig} glog.V(logger.Info).Infoln("instance:", n.serverConfig.Name) diff --git a/p2p/discv5/net.go b/p2p/discv5/net.go index 71eaec3c42..7ad6f1e5b9 100644 --- a/p2p/discv5/net.go +++ b/p2p/discv5/net.go @@ -60,14 +60,6 @@ func debugLog(s string) { } } -// BootNodes are the enode URLs of the P2P bootstrap nodes for the experimental RLPx v5 "Topic Discovery" network -// warning: local bootnodes for testing!!! -var BootNodes = []*Node{ - MustParseNode("enode://0cc5f5ffb5d9098c8b8c62325f3797f56509bff942704687b6530992ac706e2cb946b90a34f1f19548cd3c7baccbcaea354531e5983c7d1bc0dee16ce4b6440b@40.118.3.223:30305"), - MustParseNode("enode://1c7a64d76c0334b0418c004af2f67c50e36a3be60b5e4790bdac0439d21603469a85fad36f2473c9a80eb043ae60936df905fa28f1ff614c3e5dc34f15dcd2dc@40.118.3.223:30308"), - MustParseNode("enode://85c85d7143ae8bb96924f2b54f1b3e70d8c4d367af305325d30a61385a432f247d2c75c45c6b4a60335060d072d7f5b35dd1d4c45f76941f62a4f83b6e75daaf@40.118.3.223:30309"), -} - // Network manages the table and all protocol interaction. type Network struct { db *nodeDB // database of known nodes diff --git a/p2p/server.go b/p2p/server.go index 1e571abf1d..7381127dc9 100644 --- a/p2p/server.go +++ b/p2p/server.go @@ -73,16 +73,26 @@ type Config struct { // or not. Disabling is usually useful for protocol debugging (manual topology). Discovery bool + // DiscoveryV5 specifies whether the the new topic-discovery based V5 discovery + // protocol should be started or not. DiscoveryV5 bool + // Listener address for the V5 discovery protocol UDP traffic. + DiscoveryV5Addr string + // Name sets the node name of this server. // Use common.MakeName to create a name that follows existing conventions. Name string - // Bootstrap nodes are used to establish connectivity + // BootstrapNodes are used to establish connectivity // with the rest of the network. BootstrapNodes []*discover.Node + // BootstrapNodesV5 are used to establish connectivity + // with the rest of the network using the V5 discovery + // protocol. + BootstrapNodesV5 []*discv5.Node + // Static nodes are used as pre-configured connections which are always // maintained and re-connected on disconnects. StaticNodes []*discover.Node @@ -108,8 +118,6 @@ type Config struct { // the server is started. ListenAddr string - ListenAddrV5 string - // If set to a non-nil value, the given NAT port mapper // is used to make the listening port available to the // Internet. @@ -359,11 +367,11 @@ func (srv *Server) Start() (err error) { } if srv.DiscoveryV5 { - ntab, err := discv5.ListenUDP(srv.PrivateKey, srv.ListenAddrV5, srv.NAT, "") //srv.NodeDatabase) + ntab, err := discv5.ListenUDP(srv.PrivateKey, srv.DiscoveryV5Addr, srv.NAT, "") //srv.NodeDatabase) if err != nil { return err } - if err := ntab.SetFallbackNodes(discv5.BootNodes); err != nil { + if err := ntab.SetFallbackNodes(srv.BootstrapNodesV5); err != nil { return err } srv.DiscV5 = ntab