From 4eb3ad192e58bc42dec4e44b4a8be6cb36473c0f Mon Sep 17 00:00:00 2001 From: Maran Date: Mon, 12 May 2014 12:28:56 +0200 Subject: [PATCH 01/12] Made the debug line for invalid peer versions dynamic --- peer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/peer.go b/peer.go index 80ddc5142..9b8b3f2ae 100644 --- a/peer.go +++ b/peer.go @@ -549,7 +549,7 @@ func (p *Peer) handleHandshake(msg *ethwire.Msg) { c := msg.Data if c.Get(0).Uint() != ProtocolVersion { - ethutil.Config.Log.Debugln("Invalid peer version. Require protocol v5") + ethutil.Config.Log.Debugln("Invalid peer version. Require protocol:", ProtocolVersion) p.Stop() return } From 8b4ed8c505111cb570c7c694675b833ebf0bba21 Mon Sep 17 00:00:00 2001 From: Maran Date: Mon, 12 May 2014 13:39:37 +0200 Subject: [PATCH 02/12] Properly exchange peer capabilities between peers --- ethereum.go | 4 ++++ peer.go | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ethereum.go b/ethereum.go index e3140b5ce..97ea35d45 100644 --- a/ethereum.go +++ b/ethereum.go @@ -122,6 +122,10 @@ func (s *Ethereum) TxPool() *ethchain.TxPool { return s.txPool } +func (s *Ethereum) ServerCaps() Caps { + return s.serverCaps +} + func (s *Ethereum) AddPeer(conn net.Conn) { peer := NewPeer(conn, s, true) diff --git a/peer.go b/peer.go index 9b8b3f2ae..54e6af823 100644 --- a/peer.go +++ b/peer.go @@ -146,6 +146,7 @@ func NewPeer(conn net.Conn, ethereum *Ethereum, inbound bool) *Peer { port: 30303, pubkey: pubkey, blocksRequested: 10, + caps: ethereum.ServerCaps(), } } @@ -573,7 +574,6 @@ func (p *Peer) handleHandshake(msg *ethwire.Msg) { } // Catch up with the connected peer - // p.CatchupWithPeer(p.ethereum.BlockChain().CurrentBlock.Hash()) p.SyncWithBlocks() // Set the peer's caps From 7f9fd0879207b7aba6c8e27d3e0b4672cba98bfb Mon Sep 17 00:00:00 2001 From: Maran Date: Mon, 12 May 2014 15:08:21 +0200 Subject: [PATCH 03/12] Implemented proper peer checking when adding new peers We now resolve a hostname to IP before we try to compare it to the existing peer pool --- ethereum.go | 43 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/ethereum.go b/ethereum.go index 97ea35d45..0f5bd11a2 100644 --- a/ethereum.go +++ b/ethereum.go @@ -2,6 +2,7 @@ package eth import ( "container/list" + "fmt" "github.com/ethereum/eth-go/ethchain" "github.com/ethereum/eth-go/ethdb" "github.com/ethereum/eth-go/ethrpc" @@ -9,9 +10,11 @@ import ( "github.com/ethereum/eth-go/ethwire" "io/ioutil" "log" + "math/rand" "net" "net/http" "strconv" + "strings" "sync" "sync/atomic" "time" @@ -146,15 +149,51 @@ func (s *Ethereum) ConnectToPeer(addr string) error { if s.peers.Len() < s.MaxPeers { var alreadyConnected bool + ahost, _, _ := net.SplitHostPort(addr) + var chost string + + ips, err := net.LookupIP(ahost) + + if err != nil { + return err + } else { + // If more then one ip is available try stripping away the ipv6 ones + if len(ips) > 1 { + var ipsv4 []net.IP + // For now remove the ipv6 addresses + for _, ip := range ips { + if strings.Contains(ip.String(), "::") { + continue + } else { + ipsv4 = append(ipsv4, ip) + } + } + if len(ipsv4) == 0 { + return fmt.Errorf("[SERV] No IPV4 addresses available for hostname") + } + + // Pick a random ipv4 address, simulating round-robin DNS. + rand.Seed(time.Now().UTC().UnixNano()) + i := rand.Intn(len(ipsv4)) + chost = ipsv4[i].String() + } else { + if len(ips) == 0 { + return fmt.Errorf("[SERV] No IPs resolved for the given hostname") + return nil + } + chost = ips[0].String() + } + } + eachPeer(s.peers, func(p *Peer, v *list.Element) { if p.conn == nil { return } phost, _, _ := net.SplitHostPort(p.conn.RemoteAddr().String()) - ahost, _, _ := net.SplitHostPort(addr) - if phost == ahost { + if phost == chost { alreadyConnected = true + ethutil.Config.Log.Debugf("[SERV] Peer %s already added.\n", chost) return } }) From 5fcbaefd0b20af2a13ad9f6c3359b8c1ca096ba6 Mon Sep 17 00:00:00 2001 From: Maran Date: Mon, 12 May 2014 15:43:10 +0200 Subject: [PATCH 04/12] Don't forward localhost connections over the public network --- peer.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/peer.go b/peer.go index 54e6af823..d8168e455 100644 --- a/peer.go +++ b/peer.go @@ -534,7 +534,10 @@ func (p *Peer) peersMessage() *ethwire.Msg { outPeers := make([]interface{}, len(p.ethereum.InOutPeers())) // Serialise each peer for i, peer := range p.ethereum.InOutPeers() { - outPeers[i] = peer.RlpData() + // Don't return localhost as valid peer + if !net.ParseIP(peer.conn.RemoteAddr().String()).IsLoopback() { + outPeers[i] = peer.RlpData() + } } // Return the message to the peer with the known list of connected clients From 8fe0864680b40c3fa5e47775856d8ae1997ba003 Mon Sep 17 00:00:00 2001 From: Maran Date: Mon, 12 May 2014 16:09:23 +0200 Subject: [PATCH 05/12] Only accept peers if we asked for them --- peer.go | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/peer.go b/peer.go index d8168e455..359e83566 100644 --- a/peer.go +++ b/peer.go @@ -401,22 +401,22 @@ func (p *Peer) HandleInbound() { case ethwire.MsgPeersTy: // Received a list of peers (probably because MsgGetPeersTy was send) // Only act on message if we actually requested for a peers list - //if p.requestedPeerList { - data := msg.Data - // Create new list of possible peers for the ethereum to process - peers := make([]string, data.Len()) - // Parse each possible peer - for i := 0; i < data.Len(); i++ { - value := data.Get(i) - peers[i] = unpackAddr(value.Get(0), value.Get(1).Uint()) + if p.requestedPeerList { + data := msg.Data + // Create new list of possible peers for the ethereum to process + peers := make([]string, data.Len()) + // Parse each possible peer + for i := 0; i < data.Len(); i++ { + value := data.Get(i) + peers[i] = unpackAddr(value.Get(0), value.Get(1).Uint()) + } + + // Connect to the list of peers + p.ethereum.ProcessPeerList(peers) + // Mark unrequested again + p.requestedPeerList = false + } - - // Connect to the list of peers - p.ethereum.ProcessPeerList(peers) - // Mark unrequested again - p.requestedPeerList = false - - //} case ethwire.MsgGetChainTy: var parent *ethchain.Block // Length minus one since the very last element in the array is a count From 52b664b0aec24bffc040da06bbe8be1d3e7e4ab8 Mon Sep 17 00:00:00 2001 From: Maran Date: Mon, 12 May 2014 16:30:21 +0200 Subject: [PATCH 06/12] Removed peers from peerlist as soon as they disconnect. Might fix #13 We used to wait for the reaping timer to clean up the peerlist, not any longer --- peer.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/peer.go b/peer.go index 359e83566..932dbdc18 100644 --- a/peer.go +++ b/peer.go @@ -2,6 +2,7 @@ package eth import ( "bytes" + "container/list" "fmt" "github.com/ethereum/eth-go/ethchain" "github.com/ethereum/eth-go/ethutil" @@ -515,6 +516,15 @@ func (p *Peer) Stop() { p.writeMessage(ethwire.NewMessage(ethwire.MsgDiscTy, "")) p.conn.Close() } + + // Pre-emptively remove the peer; don't wait for reaping. We already know it's dead if we are here + p.ethereum.peerMut.Lock() + defer p.ethereum.peerMut.Unlock() + eachPeer(p.ethereum.peers, func(peer *Peer, e *list.Element) { + if peer == p { + p.ethereum.peers.Remove(e) + } + }) } func (p *Peer) pushHandshake() error { From cc341b8734cf2c424b9b4adf7861400992755d7a Mon Sep 17 00:00:00 2001 From: Maran Date: Mon, 12 May 2014 16:36:14 +0200 Subject: [PATCH 07/12] Added debug message if you try to add a peer when max peers has been reached. --- ethereum.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/ethereum.go b/ethereum.go index 0f5bd11a2..bd391ba37 100644 --- a/ethereum.go +++ b/ethereum.go @@ -132,9 +132,13 @@ func (s *Ethereum) ServerCaps() Caps { func (s *Ethereum) AddPeer(conn net.Conn) { peer := NewPeer(conn, s, true) - if peer != nil && s.peers.Len() < s.MaxPeers { - s.peers.PushBack(peer) - peer.Start() + if peer != nil { + if s.peers.Len() < s.MaxPeers { + s.peers.PushBack(peer) + peer.Start() + } else { + ethutil.Config.Log.Debugf("[SERV] Max connected peers reached. Not adding incoming peer.") + } } } From 3647cc5b073b9c82d50394074c978628a32719e4 Mon Sep 17 00:00:00 2001 From: Maran Date: Tue, 13 May 2014 11:35:21 +0200 Subject: [PATCH 08/12] Implemented our own makeshift go seed. Fixes #16 --- ethereum.go | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/ethereum.go b/ethereum.go index bd391ba37..92c4e4ba1 100644 --- a/ethereum.go +++ b/ethereum.go @@ -325,8 +325,21 @@ func (s *Ethereum) Start(seed bool) { } func (s *Ethereum) Seed() { - ethutil.Config.Log.Debugln("Seeding") - // DNS Bootstrapping + ethutil.Config.Log.Debugln("[SERV] Retrieving seed nodes") + + // Eth-Go Bootstrapping + ips, er := net.LookupIP("seed.bysh.me") + if er == nil { + peers := []string{} + for _, ip := range ips { + node := fmt.Sprintf("%s:%d", ip.String(), 30303) + ethutil.Config.Log.Debugln("[SERV] Found DNS Go Peer:", node) + peers = append(peers, node) + } + s.ProcessPeerList(peers) + } + + // Official DNS Bootstrapping _, nodes, err := net.LookupSRV("eth", "tcp", "ethereum.org") if err == nil { peers := []string{} @@ -340,11 +353,11 @@ func (s *Ethereum) Seed() { for _, a := range addr { // Build string out of SRV port and Resolved IP peer := net.JoinHostPort(a, port) - log.Println("Found DNS Bootstrap Peer:", peer) + ethutil.Config.Log.Debugln("[SERV] Found DNS Bootstrap Peer:", peer) peers = append(peers, peer) } } else { - log.Println("Couldn't resolve :", target) + ethutil.Config.Log.Debugln("[SERV} Couldn't resolve :", target) } } // Connect to Peer list From a9d5656a466f2d57bcf97efdc4644ca20ae8bd6b Mon Sep 17 00:00:00 2001 From: Maran Date: Tue, 13 May 2014 11:49:55 +0200 Subject: [PATCH 09/12] Added support to NewJsonRpc to return an error as well as an interface Also changed default port to 8080. Fixes #18 --- ethrpc/server.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ethrpc/server.go b/ethrpc/server.go index 40787fade..a612f1163 100644 --- a/ethrpc/server.go +++ b/ethrpc/server.go @@ -48,15 +48,15 @@ func (s *JsonRpcServer) Start() { } } -func NewJsonRpcServer(ethp *ethpub.PEthereum) *JsonRpcServer { - l, err := net.Listen("tcp", ":30304") +func NewJsonRpcServer(ethp *ethpub.PEthereum) (*JsonRpcServer, error) { + l, err := net.Listen("tcp", ":8080") if err != nil { - ethutil.Config.Log.Infoln("Error starting JSON-RPC") + return nil, err } return &JsonRpcServer{ listener: l, quit: make(chan bool), ethp: ethp, - } + }, nil } From d31303a592bcf8662fbbe66e542535e0e82c5a83 Mon Sep 17 00:00:00 2001 From: Maran Date: Tue, 13 May 2014 12:01:34 +0200 Subject: [PATCH 10/12] Implemented support for a custom RPC port --- ethrpc/server.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ethrpc/server.go b/ethrpc/server.go index a612f1163..3960e641c 100644 --- a/ethrpc/server.go +++ b/ethrpc/server.go @@ -1,6 +1,7 @@ package ethrpc import ( + "fmt" "github.com/ethereum/eth-go/ethpub" "github.com/ethereum/eth-go/ethutil" "net" @@ -48,8 +49,9 @@ func (s *JsonRpcServer) Start() { } } -func NewJsonRpcServer(ethp *ethpub.PEthereum) (*JsonRpcServer, error) { - l, err := net.Listen("tcp", ":8080") +func NewJsonRpcServer(ethp *ethpub.PEthereum, port int) (*JsonRpcServer, error) { + sport := fmt.Sprintf(":%d", port) + l, err := net.Listen("tcp", sport) if err != nil { return nil, err } From cac9562c059a94902dc420fea697026a682014bc Mon Sep 17 00:00:00 2001 From: obscuren Date: Tue, 13 May 2014 12:42:24 +0200 Subject: [PATCH 11/12] Use EthManager interface instead --- ethpub/pub.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/ethpub/pub.go b/ethpub/pub.go index f7e641b35..4ced632f5 100644 --- a/ethpub/pub.go +++ b/ethpub/pub.go @@ -6,16 +6,18 @@ import ( ) type PEthereum struct { + manager ethchain.EthManager stateManager *ethchain.StateManager blockChain *ethchain.BlockChain txPool *ethchain.TxPool } -func NewPEthereum(sm *ethchain.StateManager, bc *ethchain.BlockChain, txp *ethchain.TxPool) *PEthereum { +func NewPEthereum(manager ethchain.EthManager) *PEthereum { return &PEthereum{ - sm, - bc, - txp, + manager, + manager.StateManager(), + manager.BlockChain(), + manager.TxPool(), } } From 86d6aba0127d6f35f5dda50d08dff05581031701 Mon Sep 17 00:00:00 2001 From: obscuren Date: Tue, 13 May 2014 16:36:43 +0200 Subject: [PATCH 12/12] Bumped --- README.md | 2 +- ethutil/config.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 617a1ac8a..72e187db7 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Ethereum Ethereum Go Development package (C) Jeffrey Wilcke Ethereum is currently in its testing phase. The current state is "Proof -of Concept 5.0 RC3". For build instructions see the [Wiki](https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum(Go)). +of Concept 5.0 RC4". For build instructions see the [Wiki](https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum(Go)). Ethereum Go is split up in several sub packages Please refer to each individual package for more information. diff --git a/ethutil/config.go b/ethutil/config.go index feab23e02..07dc85f08 100644 --- a/ethutil/config.go +++ b/ethutil/config.go @@ -50,7 +50,7 @@ func ReadConfig(base string) *config { } } - Config = &config{ExecPath: path, Debug: true, Ver: "0.5.0 RC3"} + Config = &config{ExecPath: path, Debug: true, Ver: "0.5.0 RC4"} Config.Log = NewLogger(LogFile|LogStd, LogLevelDebug) Config.SetClientString("/Ethereum(G)") }