From 278183c7e727f875fb2eae8ceba29bfd4b01afc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Szil=C3=A1gyi?= Date: Tue, 26 May 2015 17:49:37 +0300 Subject: [PATCH 1/4] eth, p2p: start the p2p server even if maxpeers == 0 --- eth/backend.go | 10 +++------- p2p/server.go | 3 --- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/eth/backend.go b/eth/backend.go index aeaac788a0..73d37c5363 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -449,14 +449,10 @@ func (s *Ethereum) Start() error { ClientString: s.net.Name, ProtocolVersion: ProtocolVersion, }) - - if s.net.MaxPeers > 0 { - err := s.net.Start() - if err != nil { - return err - } + err := s.net.Start() + if err != nil { + return err } - // periodically flush databases go s.syncDatabases() diff --git a/p2p/server.go b/p2p/server.go index af08380e18..9c6e8f4db7 100644 --- a/p2p/server.go +++ b/p2p/server.go @@ -275,9 +275,6 @@ func (srv *Server) Start() (err error) { if srv.PrivateKey == nil { return fmt.Errorf("Server.PrivateKey must be set to a non-nil key") } - if srv.MaxPeers <= 0 { - return fmt.Errorf("Server.MaxPeers must be > 0") - } if srv.newTransport == nil { srv.newTransport = newRLPX } From e1a0ee8fc541bd73ac5d5a0cdacfe5265fcef833 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Szil=C3=A1gyi?= Date: Tue, 26 May 2015 19:07:24 +0300 Subject: [PATCH 2/4] cmd/geth, cmd/utils, eth, p2p: pass and honor a no discovery flag --- cmd/geth/main.go | 1 + cmd/utils/flags.go | 6 +++++- eth/backend.go | 2 ++ p2p/server.go | 37 +++++++++++++++++++++++++++++-------- 4 files changed, 37 insertions(+), 9 deletions(-) diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 56f383b776..9d935efbd4 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -260,6 +260,7 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso utils.AutoDAGFlag, utils.NATFlag, utils.NatspecEnabledFlag, + utils.NoDiscoverFlag, utils.NodeKeyFileFlag, utils.NodeKeyHexFlag, utils.RPCEnabledFlag, diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index cb774aa5bf..155110ddce 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -235,6 +235,10 @@ var ( Usage: "NAT port mapping mechanism (any|none|upnp|pmp|extip:)", Value: "any", } + NoDiscoverFlag = cli.BoolFlag{ + Name: "nodiscover", + Usage: "Disables the peer discovery mechanism (manual peer addition)", + } WhisperEnabledFlag = cli.BoolFlag{ Name: "shh", Usage: "Enable whisper", @@ -312,6 +316,7 @@ func MakeEthConfig(clientID, version string, ctx *cli.Context) *eth.Config { Port: ctx.GlobalString(ListenPortFlag.Name), NAT: GetNAT(ctx), NatSpec: ctx.GlobalBool(NatspecEnabledFlag.Name), + Discovery: !ctx.GlobalBool(NoDiscoverFlag.Name), NodeKey: GetNodeKey(ctx), Shh: ctx.GlobalBool(WhisperEnabledFlag.Name), Dial: true, @@ -320,7 +325,6 @@ func MakeEthConfig(clientID, version string, ctx *cli.Context) *eth.Config { SolcPath: ctx.GlobalString(SolcPathFlag.Name), AutoDAG: ctx.GlobalBool(AutoDAGFlag.Name) || ctx.GlobalBool(MiningEnabledFlag.Name), } - } func GetChain(ctx *cli.Context) (*core.ChainManager, common.Database, common.Database) { diff --git a/eth/backend.go b/eth/backend.go index 73d37c5363..18e214d44d 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -72,6 +72,7 @@ type Config struct { MaxPeers int MaxPendingPeers int + Discovery bool Port string // Space-separated list of discovery node URLs @@ -311,6 +312,7 @@ func New(config *Config) (*Ethereum, error) { Name: config.Name, MaxPeers: config.MaxPeers, MaxPendingPeers: config.MaxPendingPeers, + Discovery: config.Discovery, Protocols: protocols, NAT: config.NAT, NoDial: !config.Dial, diff --git a/p2p/server.go b/p2p/server.go index 9c6e8f4db7..0e814f494d 100644 --- a/p2p/server.go +++ b/p2p/server.go @@ -55,6 +55,10 @@ type Server struct { // Zero defaults to preset values. MaxPendingPeers int + // Discovery specifies whether the peer discovery mechanism should be started + // or not. Disabling is usually useful for protocol debugging (manual topology). + Discovery bool + // Name sets the node name of this server. // Use common.MakeName to create a name that follows existing conventions. Name string @@ -240,6 +244,14 @@ func (srv *Server) Self() *discover.Node { if !srv.running { return &discover.Node{IP: net.ParseIP("0.0.0.0")} } + if srv.ntab == nil { + addr := srv.listener.Addr().(*net.TCPAddr) + return &discover.Node{ + ID: discover.PubkeyID(&srv.PrivateKey.PublicKey), + IP: addr.IP, + TCP: uint16(addr.Port), + } + } return srv.ntab.Self() } @@ -290,15 +302,22 @@ func (srv *Server) Start() (err error) { srv.peerOpDone = make(chan struct{}) // node table - ntab, err := discover.ListenUDP(srv.PrivateKey, srv.ListenAddr, srv.NAT, srv.NodeDatabase) - if err != nil { - return err + if srv.Discovery { + ntab, err := discover.ListenUDP(srv.PrivateKey, srv.ListenAddr, srv.NAT, srv.NodeDatabase) + if err != nil { + return err + } + srv.ntab = ntab } - srv.ntab = ntab - dialer := newDialState(srv.StaticNodes, srv.ntab, srv.MaxPeers/2) + + dynPeers := srv.MaxPeers / 2 + if !srv.Discovery { + dynPeers = 0 + } + dialer := newDialState(srv.StaticNodes, srv.ntab, dynPeers) // handshake - srv.ourHandshake = &protoHandshake{Version: baseProtocolVersion, Name: srv.Name, ID: ntab.Self().ID} + srv.ourHandshake = &protoHandshake{Version: baseProtocolVersion, Name: srv.Name, ID: discover.PubkeyID(&srv.PrivateKey.PublicKey)} for _, p := range srv.Protocols { srv.ourHandshake.Caps = append(srv.ourHandshake.Caps, p.cap()) } @@ -454,7 +473,9 @@ running: } // Terminate discovery. If there is a running lookup it will terminate soon. - srv.ntab.Close() + if srv.ntab != nil { + srv.ntab.Close() + } // Disconnect all peers. for _, p := range peers { p.Disconnect(DiscQuitting) @@ -486,7 +507,7 @@ func (srv *Server) encHandshakeChecks(peers map[discover.NodeID]*Peer, c *conn) return DiscTooManyPeers case peers[c.id] != nil: return DiscAlreadyConnected - case c.id == srv.ntab.Self().ID: + case c.id == srv.Self().ID: return DiscSelf default: return nil From 68898a4d6bd5edf0011197ef0a68f3fe3cfd0d95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Szil=C3=A1gyi?= Date: Tue, 26 May 2015 19:16:05 +0300 Subject: [PATCH 3/4] p2p: fix Self() panic if listening is disabled --- p2p/server.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/p2p/server.go b/p2p/server.go index 0e814f494d..5890418108 100644 --- a/p2p/server.go +++ b/p2p/server.go @@ -241,10 +241,18 @@ func (srv *Server) AddPeer(node *discover.Node) { func (srv *Server) Self() *discover.Node { srv.lock.Lock() defer srv.lock.Unlock() + + // If the server's not running, return an empty node if !srv.running { return &discover.Node{IP: net.ParseIP("0.0.0.0")} } + // If the node is running but discovery is off, manually assemble the node infos if srv.ntab == nil { + // Inbound connections disabled, use zero address + if srv.listener == nil { + return &discover.Node{IP: net.ParseIP("0.0.0.0"), ID: discover.PubkeyID(&srv.PrivateKey.PublicKey)} + } + // Otherwise inject the listener address too addr := srv.listener.Addr().(*net.TCPAddr) return &discover.Node{ ID: discover.PubkeyID(&srv.PrivateKey.PublicKey), @@ -252,6 +260,7 @@ func (srv *Server) Self() *discover.Node { TCP: uint16(addr.Port), } } + // Otherwise return the live node infos return srv.ntab.Self() } From 4de8213887b26b13d18fc6da6ce159e60ddae6fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Szil=C3=A1gyi?= Date: Tue, 26 May 2015 19:35:31 +0300 Subject: [PATCH 4/4] cmd/geth: fix js console test for p2p server update --- cmd/geth/js_test.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cmd/geth/js_test.go b/cmd/geth/js_test.go index 41e1034e9f..dee25e44e6 100644 --- a/cmd/geth/js_test.go +++ b/cmd/geth/js_test.go @@ -35,6 +35,7 @@ const ( var ( versionRE = regexp.MustCompile(strconv.Quote(`"compilerVersion":"` + solcVersion + `"`)) + testNodeKey = crypto.ToECDSA(common.Hex2Bytes("4b50fa71f5c3eeb8fdc452224b2395af2fcc3d125e06c32c82e048c0559db03f")) testGenesis = `{"` + testAddress[2:] + `": {"balance": "` + testBalance + `"}}` ) @@ -72,6 +73,7 @@ func testJEthRE(t *testing.T) (string, *testjethre, *eth.Ethereum) { ks := crypto.NewKeyStorePlain(filepath.Join(tmp, "keystore")) am := accounts.NewManager(ks) ethereum, err := eth.New(ð.Config{ + NodeKey: testNodeKey, DataDir: tmp, AccountManager: am, MaxPeers: 0, @@ -122,7 +124,7 @@ func TestNodeInfo(t *testing.T) { } defer ethereum.Stop() defer os.RemoveAll(tmp) - want := `{"DiscPort":0,"IP":"0.0.0.0","ListenAddr":"","Name":"test","NodeID":"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","NodeUrl":"enode://00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000@0.0.0.0:0","TCPPort":0,"Td":"0"}` + want := `{"DiscPort":0,"IP":"0.0.0.0","ListenAddr":"","Name":"test","NodeID":"4cb2fc32924e94277bf94b5e4c983beedb2eabd5a0bc941db32202735c6625d020ca14a5963d1738af43b6ac0a711d61b1a06de931a499fe2aa0b1a132a902b5","NodeUrl":"enode://4cb2fc32924e94277bf94b5e4c983beedb2eabd5a0bc941db32202735c6625d020ca14a5963d1738af43b6ac0a711d61b1a06de931a499fe2aa0b1a132a902b5@0.0.0.0:0","TCPPort":0,"Td":"131072"}` checkEvalJSON(t, repl, `admin.nodeInfo()`, want) }