From b61f48e5aad9cf897f5655a0db002a3349109c67 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C3=A9ter=20Szil=C3=A1gyi?= <peterke@gmail.com>
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 1947030fc..50b658467 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 a0b305d4a..0b18d9f79 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 9b221a874..bb421fc87 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://<hex node id>@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 85ac7fec5..4d1f48ec3 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 dbefcb8a5..62655f237 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 fb11696fa..d49ae3a45 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 71eaec3c4..7ad6f1e5b 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 1e571abf1..7381127dc 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
-- 
GitLab