diff --git a/config.default.json b/config.default.json index bf4fcd9ef7beed579ed7f18be8253e78391b3385..25816877fa7f7861cec47e6db5a2be922f4076e8 100644 --- a/config.default.json +++ b/config.default.json @@ -14,8 +14,7 @@ "entryNodes": [ "MRCJTGX9x+PPiT3um1DQSHXvALaUg/tCH/oQr6mliGo=@35.246.104.243:14626" ], - "port": 14626, - "version": 1 + "port": 14626 }, "dashboard": { "bindAddress": "127.0.0.1:8081", diff --git a/go.mod b/go.mod index 0dbff93702cc3c219d93d38413c19ea26a9cf060..a838712d43511b98bdcd369ec46a791d14904901 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/googollee/go-engine.io v1.4.3-0.20190924125625-798118fc0dd2 github.com/googollee/go-socket.io v1.4.3-0.20191204093753-683f8725b6d0 github.com/gorilla/websocket v1.4.1 - github.com/iotaledger/hive.go v0.0.0-20200316213914-76b7a4169e64 + github.com/iotaledger/hive.go v0.0.0-20200323150914-f38e680ea7d1 github.com/iotaledger/iota.go v1.0.0-beta.14 github.com/labstack/echo v3.3.10+incompatible github.com/labstack/gommon v0.3.0 // indirect @@ -21,7 +21,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.6.2 - github.com/stretchr/testify v1.4.0 + github.com/stretchr/testify v1.5.1 github.com/valyala/fasttemplate v1.1.0 // indirect go.uber.org/atomic v1.6.0 go.uber.org/zap v1.14.0 @@ -29,3 +29,5 @@ require ( golang.org/x/net v0.0.0-20200301022130-244492dfa37a gopkg.in/src-d/go-git.v4 v4.13.1 ) + +replace github.com/iotaledger/hive.go v0.0.0 => ../hive.go diff --git a/go.sum b/go.sum index 18faf70e16059b5918e94f6078f178f1d63feba0..9fca25e7e54c8f86f4d906784e0aa79f4f34d934 100644 --- a/go.sum +++ b/go.sum @@ -130,8 +130,10 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/iotaledger/hive.go v0.0.0-20200316213914-76b7a4169e64 h1:O+1g39PWKzskXCViRD07ePv6183gDbH81XoShbPTzuc= -github.com/iotaledger/hive.go v0.0.0-20200316213914-76b7a4169e64/go.mod h1:0LQvxKmfU4bcQcjYIAq3PRfsA5584U0AioAAas6/QU8= +github.com/iotaledger/hive.go v0.0.0-20200319204115-e052cf07c81d h1:bwrSVMHIVROkg6wkdg2MmMRrzRwGORjNBl7LHJzp3+0= +github.com/iotaledger/hive.go v0.0.0-20200319204115-e052cf07c81d/go.mod h1:EfH+ZcYGFJzzoFpO7NHGi2k7+Xc84ASyp1EwjhI3eJc= +github.com/iotaledger/hive.go v0.0.0-20200323150914-f38e680ea7d1 h1:ActziRcYMPDnccHya7NKtwsPCIL5B9WcSE/g6ZFcAew= +github.com/iotaledger/hive.go v0.0.0-20200323150914-f38e680ea7d1/go.mod h1:EfH+ZcYGFJzzoFpO7NHGi2k7+Xc84ASyp1EwjhI3eJc= github.com/iotaledger/iota.go v1.0.0-beta.9/go.mod h1:F6WBmYd98mVjAmmPVYhnxg8NNIWCjjH8VWT9qvv3Rc8= github.com/iotaledger/iota.go v1.0.0-beta.14 h1:Oeb28MfBuJEeXcGrLhTCJFtbsnc8y1u7xidsAmiOD5A= github.com/iotaledger/iota.go v1.0.0-beta.14/go.mod h1:F6WBmYd98mVjAmmPVYhnxg8NNIWCjjH8VWT9qvv3Rc8= @@ -289,6 +291,8 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= diff --git a/packages/database/versioning.go b/packages/database/versioning.go index a848eb0e508a7ecbf3b9c61773700fdfdaa79b1c..5150bc624dcd1bbdea419dffab416c7105fd562c 100644 --- a/packages/database/versioning.go +++ b/packages/database/versioning.go @@ -8,7 +8,7 @@ import ( const ( // DBVersion defines the version of the database schema this version of GoShimmer supports. // everytime there's a breaking change regarding the stored data, this version flag should be adjusted. - DBVersion = 1 + DBVersion = 2 ) var ( diff --git a/packages/gossip/common.go b/packages/gossip/common.go index 237e11ab3608c0d557ee7e84533e8ef4f21afea4..854d7214deccf4d4e64bd4df3e4d7c9fc4f481b3 100644 --- a/packages/gossip/common.go +++ b/packages/gossip/common.go @@ -1,6 +1,9 @@ package gossip import ( + "net" + "strconv" + "github.com/iotaledger/hive.go/autopeering/peer" "github.com/iotaledger/hive.go/autopeering/peer/service" ) @@ -12,9 +15,9 @@ func IsSupported(p *peer.Peer) bool { // GetAddress returns the address of the gossip service. func GetAddress(p *peer.Peer) string { - gossip := p.Services().Get(service.GossipKey) - if gossip == nil { - panic("peer does not support gossip") + gossipEndpoint := p.Services().Get(service.GossipKey) + if gossipEndpoint == nil { + panic("peer does not support gossipEndpoint") } - return gossip.String() + return net.JoinHostPort(p.IP().String(), strconv.Itoa(gossipEndpoint.Port())) } diff --git a/packages/gossip/manager_test.go b/packages/gossip/manager_test.go index f91adc10327492e87fcd33423c15653fa626a72c..220f55134afb7dffb6c5d7eff0a5ac800af5ccca 100644 --- a/packages/gossip/manager_test.go +++ b/packages/gossip/manager_test.go @@ -380,18 +380,17 @@ func newTestDB(t require.TestingT) *peer.DB { func newTestManager(t require.TestingT, name string) (*Manager, func(), *peer.Peer) { l := log.Named(name) - services := service.New() - services.Update(service.PeeringKey, "peering", name) - local, err := peer.NewLocal(services, newTestDB(t)) - require.NoError(t, err) - laddr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:0") require.NoError(t, err) lis, err := net.ListenTCP("tcp", laddr) require.NoError(t, err) - // enable TCP gossipping - require.NoError(t, local.UpdateService(service.GossipKey, lis.Addr().Network(), lis.Addr().String())) + services := service.New() + services.Update(service.PeeringKey, "peering", 0) + services.Update(service.GossipKey, lis.Addr().Network(), lis.Addr().(*net.TCPAddr).Port) + + local, err := peer.NewLocal(lis.Addr().(*net.TCPAddr).IP, services, newTestDB(t)) + require.NoError(t, err) srv := server.ServeTCP(local, lis, l) @@ -404,7 +403,7 @@ func newTestManager(t require.TestingT, name string) (*Manager, func(), *peer.Pe srv.Close() _ = lis.Close() } - return mgr, detach, &local.Peer + return mgr, detach, local.Peer } func newEventMock(t mock.TestingT) (*eventMock, func()) { diff --git a/packages/gossip/neighbor_test.go b/packages/gossip/neighbor_test.go index 36c61534baf178c3fd637406302661e6b75687bd..2ec1a2be9349dae2367d831b4367ae58b1baec00 100644 --- a/packages/gossip/neighbor_test.go +++ b/packages/gossip/neighbor_test.go @@ -1,6 +1,7 @@ package gossip import ( + "crypto/ed25519" "net" "sync" "sync/atomic" @@ -118,15 +119,16 @@ func TestNeighborParallelWrite(t *testing.T) { } func newTestNeighbor(name string, conn net.Conn) *Neighbor { - return NewNeighbor(newTestPeer(name, conn.LocalAddr()), conn, log.Named(name)) + return NewNeighbor(newTestPeer(name, conn), conn, log.Named(name)) } -func newTestPeer(name string, addr net.Addr) *peer.Peer { +func newTestPeer(name string, conn net.Conn) *peer.Peer { services := service.New() - services.Update(service.PeeringKey, addr.Network(), addr.String()) - services.Update(service.GossipKey, addr.Network(), addr.String()) - - return peer.NewPeer([]byte(name), services) + services.Update(service.PeeringKey, conn.LocalAddr().Network(), 0) + services.Update(service.GossipKey, conn.LocalAddr().Network(), 0) + key := make([]byte, ed25519.PublicKeySize) + copy(key, name) + return peer.NewPeer(key, net.IPv4zero, services) } func newPipe() (net.Conn, net.Conn, func()) { diff --git a/packages/gossip/server/handshake.go b/packages/gossip/server/handshake.go index 719ff0dea33ce26994ba2bf83b4bea904a8ed356..86bef3f74ad82ab7aea532c1476661bf713ba4a1 100644 --- a/packages/gossip/server/handshake.go +++ b/packages/gossip/server/handshake.go @@ -50,13 +50,6 @@ func (t *TCP) validateHandshakeRequest(reqData []byte) bool { ) return false } - if m.GetTo() != t.publicAddr.String() { - t.log.Debugw("invalid handshake", - "to", m.GetTo(), - "want", t.publicAddr.String(), - ) - return false - } if isExpired(m.GetTimestamp()) { t.log.Debugw("invalid handshake", "timestamp", time.Unix(m.GetTimestamp(), 0), diff --git a/packages/gossip/server/server.go b/packages/gossip/server/server.go index 6fe98d5363f6eb4ea87e09c13fb54f8d9fc88b67..80a1d183b1258a7f1a28434790a0d13759b6300b 100644 --- a/packages/gossip/server/server.go +++ b/packages/gossip/server/server.go @@ -7,6 +7,7 @@ import ( "fmt" "io" "net" + "strconv" "strings" "sync" "time" @@ -46,10 +47,9 @@ var dialRetryPolicy = backoff.ConstantBackOff(500 * time.Millisecond).With(backo // TCP establishes verified incoming and outgoing TCP connections to other peers. type TCP struct { - local *peer.Local - publicAddr net.Addr - listener *net.TCPListener - log *zap.SugaredLogger + local *peer.Local + listener *net.TCPListener + log *zap.SugaredLogger addAcceptMatcher chan *acceptMatcher acceptReceived chan accept @@ -81,16 +81,12 @@ type accept struct { func ServeTCP(local *peer.Local, listener *net.TCPListener, log *zap.SugaredLogger) *TCP { t := &TCP{ local: local, - publicAddr: local.Services().Get(service.GossipKey), listener: listener, log: log, addAcceptMatcher: make(chan *acceptMatcher), acceptReceived: make(chan accept), closing: make(chan struct{}), } - if t.publicAddr == nil { - panic(ErrNoGossip) - } t.log.Debugw("server started", "network", listener.Addr().Network(), @@ -123,21 +119,22 @@ func (t *TCP) LocalAddr() net.Addr { // DialPeer establishes a gossip connection to the given peer. // If the peer does not accept the connection or the handshake fails, an error is returned. func (t *TCP) DialPeer(p *peer.Peer) (net.Conn, error) { - gossipAddr := p.Services().Get(service.GossipKey) - if gossipAddr == nil { + gossipEndpoint := p.Services().Get(service.GossipKey) + if gossipEndpoint == nil { return nil, ErrNoGossip } var conn net.Conn if err := backoff.Retry(dialRetryPolicy, func() error { var err error - conn, err = net.DialTimeout(gossipAddr.Network(), gossipAddr.String(), dialTimeout) + address := net.JoinHostPort(p.IP().String(), strconv.Itoa(gossipEndpoint.Port())) + conn, err = net.DialTimeout("tcp", address, dialTimeout) if err != nil { - return fmt.Errorf("dial %s / %s failed: %w", gossipAddr.String(), p.ID(), err) + return fmt.Errorf("dial %s / %s failed: %w", address, p.ID(), err) } - if err = t.doHandshake(p.PublicKey(), gossipAddr.String(), conn); err != nil { - return fmt.Errorf("handshake %s / %s failed: %w", gossipAddr.String(), p.ID(), err) + if err = t.doHandshake(p.PublicKey(), address, conn); err != nil { + return fmt.Errorf("handshake %s / %s failed: %w", address, p.ID(), err) } return nil }); err != nil { @@ -154,15 +151,15 @@ func (t *TCP) DialPeer(p *peer.Peer) (net.Conn, error) { // AcceptPeer awaits an incoming connection from the given peer. // If the peer does not establish the connection or the handshake fails, an error is returned. func (t *TCP) AcceptPeer(p *peer.Peer) (net.Conn, error) { - gossipAddr := p.Services().Get(service.GossipKey) - if gossipAddr == nil { + gossipEndpoint := p.Services().Get(service.GossipKey) + if gossipEndpoint == nil { return nil, ErrNoGossip } // wait for the connection connected := <-t.acceptPeer(p) if connected.err != nil { - return nil, fmt.Errorf("accept %s / %s failed: %w", gossipAddr.String(), p.ID(), connected.err) + return nil, fmt.Errorf("accept %s / %s failed: %w", net.JoinHostPort(p.IP().String(), strconv.Itoa(gossipEndpoint.Port())), p.ID(), connected.err) } t.log.Debugw("incoming connection established", diff --git a/packages/gossip/server/server_test.go b/packages/gossip/server/server_test.go index 602968e3dda75974e86cf43c7964940f85d08ae2..983856704860aaa927a444461ada7838f09fc8da 100644 --- a/packages/gossip/server/server_test.go +++ b/packages/gossip/server/server_test.go @@ -19,7 +19,7 @@ const graceTime = 5 * time.Millisecond var log = logger.NewExampleLogger("server") func getPeer(t *TCP) *peer.Peer { - return &t.local.Peer + return t.local.Peer } func TestClose(t *testing.T) { @@ -57,8 +57,8 @@ func TestUnansweredDial(t *testing.T) { // create peer with invalid gossip address services := getPeer(transA).Services().CreateRecord() - services.Update(service.GossipKey, "tcp", "localhost:0") - unreachablePeer := peer.NewPeer(getPeer(transA).PublicKey(), services) + services.Update(service.GossipKey, "tcp", 0) + unreachablePeer := peer.NewPeer(getPeer(transA).PublicKey(), net.ParseIP("127.0.0.1"), services) _, err := transA.DialPeer(unreachablePeer) assert.Error(t, err) @@ -81,8 +81,8 @@ func TestNoHandshakeResponse(t *testing.T) { // create peer for the listener services := getPeer(transA).Services().CreateRecord() - services.Update(service.GossipKey, lis.Addr().Network(), lis.Addr().String()) - p := peer.NewPeer(getPeer(transA).PublicKey(), services) + services.Update(service.GossipKey, lis.Addr().Network(), lis.Addr().(*net.TCPAddr).Port) + p := peer.NewPeer(getPeer(transA).PublicKey(), lis.Addr().(*net.TCPAddr).IP, services) _, err = transA.DialPeer(p) assert.Error(t, err) @@ -174,18 +174,17 @@ func newTestDB(t require.TestingT) *peer.DB { func newTestServer(t require.TestingT, name string) (*TCP, func()) { l := log.Named(name) - services := service.New() - services.Update(service.PeeringKey, "peering", name) - local, err := peer.NewLocal(services, newTestDB(t)) - require.NoError(t, err) - laddr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:0") require.NoError(t, err) lis, err := net.ListenTCP("tcp", laddr) require.NoError(t, err) - // enable TCP gossipping - require.NoError(t, local.UpdateService(service.GossipKey, lis.Addr().Network(), lis.Addr().String())) + services := service.New() + services.Update(service.PeeringKey, "peering", 0) + services.Update(service.GossipKey, lis.Addr().Network(), lis.Addr().(*net.TCPAddr).Port) + + local, err := peer.NewLocal(lis.Addr().(*net.TCPAddr).IP, services, newTestDB(t)) + require.NoError(t, err) srv := ServeTCP(local, lis, l) diff --git a/plugins/autopeering/autopeering.go b/plugins/autopeering/autopeering.go index 78392512d9f26c4282a339a1019eb16283ded86c..658c39be6c7063fcf39041ac4ce660bf5c2bb41b 100644 --- a/plugins/autopeering/autopeering.go +++ b/plugins/autopeering/autopeering.go @@ -4,21 +4,28 @@ import ( "encoding/base64" "errors" "fmt" + "hash/fnv" "net" + "strconv" "strings" + "github.com/iotaledger/goshimmer/plugins/autopeering/local" + "github.com/iotaledger/goshimmer/plugins/banner" + "github.com/iotaledger/goshimmer/plugins/config" + "github.com/iotaledger/goshimmer/plugins/gossip" "github.com/iotaledger/hive.go/autopeering/discover" "github.com/iotaledger/hive.go/autopeering/peer" "github.com/iotaledger/hive.go/autopeering/peer/service" "github.com/iotaledger/hive.go/autopeering/selection" "github.com/iotaledger/hive.go/autopeering/server" - "github.com/iotaledger/hive.go/autopeering/transport" "github.com/iotaledger/hive.go/logger" "github.com/iotaledger/hive.go/node" +) - "github.com/iotaledger/goshimmer/plugins/autopeering/local" - "github.com/iotaledger/goshimmer/plugins/config" - "github.com/iotaledger/goshimmer/plugins/gossip" +// autopeering constants +const ( + ProtocolVersion = 0 // update on protocol changes + NetworkVersion = "v0.2" // update on network changes ) var ( @@ -27,11 +34,32 @@ var ( // Selection is the peer selection protocol. Selection *selection.Protocol - ErrParsingMasterNode = errors.New("can't parse master node") + // ErrParsingMasterNode is returned for an invalid master node + ErrParsingMasterNode = errors.New("cannot parse master node") + + // NetworkID specifies the autopeering network identifier + NetworkID = hash32([]byte(banner.AppVersion + NetworkVersion)) log *logger.Logger ) +func hash32(b []byte) uint32 { + hash := fnv.New32() + _, err := hash.Write(b) + if err != nil { + panic(err) + } + return hash.Sum32() +} + +// GetBindAddress returns the string form of the autopeering bind address. +func GetBindAddress() string { + peering := local.GetInstance().Services().Get(service.PeeringKey) + host := config.Node.GetString(local.CFG_BIND) + port := strconv.Itoa(peering.Port()) + return net.JoinHostPort(host, port) +} + func configureAP() { masterPeers, err := parseEntryNodes() if err != nil { @@ -39,13 +67,11 @@ func configureAP() { } log.Debugf("Master peers: %v", masterPeers) - Discovery = discover.New(local.GetInstance(), + Discovery = discover.New(local.GetInstance(), ProtocolVersion, NetworkID, discover.Logger(log.Named("disc")), - discover.Version(config.Node.GetUint32(CFG_VERSION)), discover.MasterPeers(masterPeers), ) - log.Infof("Protocol Version: %v", discover.VersionNum) // enable peer selection only when gossip is enabled if !node.IsSkipped(gossip.PLUGIN) { Selection = selection.New(local.GetInstance(), Discovery, @@ -58,57 +84,42 @@ func configureAP() { // isValidNeighbor checks whether a peer is a valid neighbor. func isValidNeighbor(p *peer.Peer) bool { // gossip must be supported - gossipAddr := p.Services().Get(service.GossipKey) - if gossipAddr == nil { + gossipService := p.Services().Get(service.GossipKey) + if gossipService == nil { return false } - // the host for the gossip and peering service must be identical - gossipHost, _, err := net.SplitHostPort(gossipAddr.String()) - if err != nil { + // gossip service must be valid + if gossipService.Network() != "tcp" || gossipService.Port() < 0 || gossipService.Port() > 65535 { return false } - peeringAddr := p.Services().Get(service.PeeringKey) - peeringHost, _, err := net.SplitHostPort(peeringAddr.String()) - if err != nil { - return false - } - return gossipHost == peeringHost + return true } func start(shutdownSignal <-chan struct{}) { defer log.Info("Stopping " + name + " ... done") lPeer := local.GetInstance() - // use the port of the peering service - peeringAddr := lPeer.Services().Get(service.PeeringKey) - _, peeringPort, err := net.SplitHostPort(peeringAddr.String()) - if err != nil { - panic(err) - } + peering := lPeer.Services().Get(service.PeeringKey) + // resolve the bind address - address := net.JoinHostPort(config.Node.GetString(local.CFG_BIND), peeringPort) - localAddr, err := net.ResolveUDPAddr(peeringAddr.Network(), address) + localAddr, err := net.ResolveUDPAddr(peering.Network(), GetBindAddress()) if err != nil { log.Fatalf("Error resolving %s: %v", local.CFG_BIND, err) } - conn, err := net.ListenUDP(peeringAddr.Network(), localAddr) + conn, err := net.ListenUDP(peering.Network(), localAddr) if err != nil { log.Fatalf("Error listening: %v", err) } defer conn.Close() - // use the UDP connection for transport - trans := transport.Conn(conn, func(network, address string) (net.Addr, error) { return net.ResolveUDPAddr(network, address) }) - defer trans.Close() - handlers := []server.Handler{Discovery} if Selection != nil { handlers = append(handlers, Selection) } // start a server doing discovery and peering - srv := server.Serve(lPeer, trans, log.Named("srv"), handlers...) + srv := server.Serve(lPeer, conn, log.Named("srv"), handlers...) defer srv.Close() // start the discovery on that connection @@ -121,7 +132,7 @@ func start(shutdownSignal <-chan struct{}) { defer Selection.Close() } - log.Infof("%s started: ID=%s Address=%s/%s", name, lPeer.ID(), peeringAddr.String(), peeringAddr.Network()) + log.Infof("%s started: ID=%s Address=%s/%s", name, lPeer.ID(), localAddr.String(), localAddr.Network()) <-shutdownSignal @@ -143,13 +154,17 @@ func parseEntryNodes() (result []*peer.Peer, err error) { } pubKey, err := base64.StdEncoding.DecodeString(parts[0]) if err != nil { - return nil, fmt.Errorf("%w: can't decode public key: %s", ErrParsingMasterNode, err) + return nil, fmt.Errorf("%w: invalid public key: %s", ErrParsingMasterNode, err) + } + addr, err := net.ResolveUDPAddr("udp", parts[1]) + if err != nil { + return nil, fmt.Errorf("%w: host cannot be resolved: %s", ErrParsingMasterNode, err) } services := service.New() - services.Update(service.PeeringKey, "udp", parts[1]) + services.Update(service.PeeringKey, addr.Network(), addr.Port) - result = append(result, peer.NewPeer(pubKey, services)) + result = append(result, peer.NewPeer(pubKey, addr.IP, services)) } return result, nil diff --git a/plugins/autopeering/local/local.go b/plugins/autopeering/local/local.go index 1586cbff8862e41177d918c4b18b6409800aada3..4a7c7e84515491ea2a071200aad6f1eaccc235cd 100644 --- a/plugins/autopeering/local/local.go +++ b/plugins/autopeering/local/local.go @@ -4,14 +4,12 @@ import ( "crypto/ed25519" "encoding/base64" "net" - "strconv" "strings" "sync" "github.com/iotaledger/hive.go/autopeering/peer" "github.com/iotaledger/hive.go/autopeering/peer/service" "github.com/iotaledger/hive.go/logger" - "github.com/iotaledger/hive.go/netutil" "github.com/iotaledger/goshimmer/packages/database" "github.com/iotaledger/goshimmer/plugins/config" @@ -25,30 +23,28 @@ var ( func configureLocal() *peer.Local { log := logger.NewLogger("Local") - var externalIP net.IP + var peeringIP net.IP if str := config.Node.GetString(CFG_EXTERNAL); strings.ToLower(str) == "auto" { - log.Info("Querying external IP ...") - ip, err := netutil.GetPublicIP(false) - if err != nil { - log.Fatalf("Error querying external IP: %s", err) - } - log.Infof("External IP queried: address=%s", ip.String()) - externalIP = ip + // let the autopeering discover the IP + peeringIP = net.IPv4zero } else { - externalIP = net.ParseIP(str) - if externalIP == nil { + peeringIP = net.ParseIP(str) + if peeringIP == nil { log.Fatalf("Invalid IP address (%s): %s", CFG_EXTERNAL, str) } - } - if !externalIP.IsGlobalUnicast() { - log.Warnf("IP is not a global unicast address: %s", externalIP.String()) + if !peeringIP.IsGlobalUnicast() { + log.Warnf("IP is not a global unicast address: %s", peeringIP.String()) + } } - peeringPort := strconv.Itoa(config.Node.GetInt(CFG_PORT)) + peeringPort := config.Node.GetInt(CFG_PORT) + if 0 > peeringPort || peeringPort > 65535 { + log.Fatalf("Invalid port number (%s): %d", CFG_PORT, peeringPort) + } // announce the peering service services := service.New() - services.Update(service.PeeringKey, "udp", net.JoinHostPort(externalIP.String(), peeringPort)) + services.Update(service.PeeringKey, "udp", peeringPort) // set the private key from the seed provided in the config var seed [][]byte @@ -75,7 +71,7 @@ func configureLocal() *peer.Local { // key, _ := peerDB.LocalPrivateKey() // fmt.Println(base64.StdEncoding.EncodeToString(ed25519.PrivateKey(key).Seed())) - local, err := peer.NewLocal(services, peerDB, seed...) + local, err := peer.NewLocal(peeringIP, services, peerDB, seed...) if err != nil { log.Fatalf("Error creating local: %s", err) } diff --git a/plugins/autopeering/parameters.go b/plugins/autopeering/parameters.go index bafa1e0b6220f66bec79f6cd30368b0163b6c32b..138b8d56e451c9024fd85c1b4296965337061c4d 100644 --- a/plugins/autopeering/parameters.go +++ b/plugins/autopeering/parameters.go @@ -6,10 +6,8 @@ import ( const ( CFG_ENTRY_NODES = "autopeering.entryNodes" - CFG_VERSION = "autopeering.version" ) func init() { flag.StringSlice(CFG_ENTRY_NODES, []string{"V8LYtWWcPYYDTTXLeIEFjJEuWlsjDiI0+Pq/Cx9ai6g=@116.202.49.178:14626"}, "list of trusted entry nodes for auto peering") - flag.Uint32(CFG_VERSION, 0, "Autopeering Protocol Version") } diff --git a/plugins/gossip/gossip.go b/plugins/gossip/gossip.go index c32d37d8ceb990965a4b78c7f7c902e7cbe11a38..d611032d64f0dc8890189f819f27cefb9ab0c330 100644 --- a/plugins/gossip/gossip.go +++ b/plugins/gossip/gossip.go @@ -7,6 +7,7 @@ import ( "github.com/iotaledger/hive.go/autopeering/peer/service" "github.com/iotaledger/hive.go/logger" + "github.com/iotaledger/hive.go/netutil" "github.com/iotaledger/goshimmer/packages/binary/tangle/model/message" gp "github.com/iotaledger/goshimmer/packages/gossip" @@ -25,19 +26,15 @@ var ( func configureGossip() { lPeer := local.GetInstance() - peeringAddr := lPeer.Services().Get(service.PeeringKey) - external, _, err := net.SplitHostPort(peeringAddr.String()) - if err != nil { - panic(err) + // announce the gossip service + gossipPort := config.Node.GetInt(GOSSIP_PORT) + if !netutil.IsValidPort(gossipPort) { + log.Fatalf("Invalid port number (%s): %d", GOSSIP_PORT, gossipPort) } - // announce the gossip service - gossipPort := strconv.Itoa(config.Node.GetInt(GOSSIP_PORT)) - err = lPeer.UpdateService(service.GossipKey, "tcp", net.JoinHostPort(external, gossipPort)) - if err != nil { + if err := lPeer.UpdateService(service.GossipKey, "tcp", gossipPort); err != nil { log.Fatalf("could not update services: %s", err) } - mgr = gp.NewManager(lPeer, getTransaction, log) } @@ -45,20 +42,18 @@ func start(shutdownSignal <-chan struct{}) { defer log.Info("Stopping " + name + " ... done") lPeer := local.GetInstance() + // use the port of the gossip service - gossipAddr := lPeer.Services().Get(service.GossipKey) - _, gossipPort, err := net.SplitHostPort(gossipAddr.String()) - if err != nil { - panic(err) - } + gossipEndpoint := lPeer.Services().Get(service.GossipKey) + // resolve the bind address - address := net.JoinHostPort(config.Node.GetString(local.CFG_BIND), gossipPort) - localAddr, err := net.ResolveTCPAddr(gossipAddr.Network(), address) + address := net.JoinHostPort(config.Node.GetString(local.CFG_BIND), strconv.Itoa(gossipEndpoint.Port())) + localAddr, err := net.ResolveTCPAddr(gossipEndpoint.Network(), address) if err != nil { log.Fatalf("Error resolving %s: %v", local.CFG_BIND, err) } - listener, err := net.ListenTCP(gossipAddr.Network(), localAddr) + listener, err := net.ListenTCP(gossipEndpoint.Network(), localAddr) if err != nil { log.Fatalf("Error listening: %v", err) } @@ -70,7 +65,7 @@ func start(shutdownSignal <-chan struct{}) { mgr.Start(srv) defer mgr.Close() - log.Infof("%s started: Address=%s/%s", name, gossipAddr.String(), gossipAddr.Network()) + log.Infof("%s started: Address=%s/%s", name, localAddr.String(), localAddr.Network()) <-shutdownSignal log.Info("Stopping " + name + " ...") diff --git a/plugins/portcheck/plugin.go b/plugins/portcheck/plugin.go index 09f25947361b5145329dbe9f8087ea7a99e45481..202c8bb4593cd3f72fad996d5ed50f2959ae6c77 100644 --- a/plugins/portcheck/plugin.go +++ b/plugins/portcheck/plugin.go @@ -2,18 +2,14 @@ package portcheck import ( "net" - "sync" - "github.com/iotaledger/goshimmer/packages/gossip/server" "github.com/iotaledger/goshimmer/plugins/autopeering" "github.com/iotaledger/goshimmer/plugins/autopeering/local" "github.com/iotaledger/goshimmer/plugins/banner" - "github.com/iotaledger/goshimmer/plugins/config" - "github.com/iotaledger/goshimmer/plugins/gossip" - + "github.com/iotaledger/hive.go/autopeering/discover" "github.com/iotaledger/hive.go/autopeering/peer/service" + "github.com/iotaledger/hive.go/autopeering/server" "github.com/iotaledger/hive.go/logger" - "github.com/iotaledger/hive.go/netutil" "github.com/iotaledger/hive.go/node" ) @@ -26,99 +22,51 @@ var ( log *logger.Logger ) -func configure(plugin *node.Plugin) { +func configure(*node.Plugin) { log = logger.NewLogger(PLUGIN_NAME) } -func run(ctx *node.Plugin) { - if !node.IsSkipped(autopeering.PLUGIN) { - log.Info("Testing autopeering service ...") - checkAutopeeringConnection() - log.Info("Testing autopeering service ... done") - } - - if !node.IsSkipped(gossip.PLUGIN) { - log.Info("Testing gossip service ...") - checkGossipConnection() - log.Info("Testing gossip service ... done") - } +func run(*node.Plugin) { + log.Info("Testing autopeering service ...") + checkAutopeeringConnection() + log.Info("Testing autopeering service ... done") } // check that discovery is working and the port is open func checkAutopeeringConnection() { peering := local.GetInstance().Services().Get(service.PeeringKey) - // use the port of the peering service - _, peeringPort, err := net.SplitHostPort(peering.String()) - if err != nil { - panic(err) - } - - // resolve the bind address - address := net.JoinHostPort(config.Node.GetString(local.CFG_BIND), peeringPort) - localAddr, err := net.ResolveUDPAddr(peering.Network(), address) - if err != nil { - log.Fatalf("Error resolving %s: %v", local.CFG_BIND, err) - } - - remoteAddr, err := net.ResolveUDPAddr(peering.Network(), peering.String()) - if err != nil { - panic(err) - } - - // do not check address and port as a NAT may change them for local connections - err = netutil.CheckUDP(localAddr, remoteAddr, false, false) - if err != nil { - log.Errorf("Error testing autopeering service: %s", err) - log.Panicf("Please check that %s is publicly reachable at %s/%s", - banner.AppName, peering.String(), peering.Network()) - } -} - -// check that the gossip server is working and the port is open -func checkGossipConnection() { - // listen on TCP gossip port - lPeer := local.GetInstance() - // use the port of the gossip service - gossipAddr := lPeer.Services().Get(service.GossipKey) - _, gossipPort, err := net.SplitHostPort(gossipAddr.String()) - if err != nil { - panic(err) - } - // resolve the bind address - address := net.JoinHostPort(config.Node.GetString(local.CFG_BIND), gossipPort) - localAddr, err := net.ResolveTCPAddr(gossipAddr.Network(), address) + localAddr, err := net.ResolveUDPAddr(peering.Network(), autopeering.GetBindAddress()) if err != nil { log.Fatalf("Error resolving %s: %v", local.CFG_BIND, err) } - - listener, err := net.ListenTCP(gossipAddr.Network(), localAddr) + // open a connection + conn, err := net.ListenUDP(peering.Network(), localAddr) if err != nil { log.Fatalf("Error listening: %v", err) } - defer listener.Close() + defer conn.Close() - srv := server.ServeTCP(lPeer, listener, log) + // create a new discovery server for the port check + disc := discover.New(local.GetInstance(), autopeering.ProtocolVersion, autopeering.NetworkID, discover.Logger(log)) + srv := server.Serve(local.GetInstance(), conn, log, disc) defer srv.Close() - // do the actual check - var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() - conn, acceptErr := srv.AcceptPeer(&lPeer.Peer) - if acceptErr != nil { - return + disc.Start(srv) + defer disc.Close() + + for _, master := range autopeering.Discovery.GetMasterPeers() { + err = disc.Ping(master) + if err == nil { + log.Infof("Pong received from %s", master.IP()) + break } - _ = conn.Close() - }() - conn, err := srv.DialPeer(&lPeer.Peer) + log.Warnf("Error pinging entry node %s: %s", master.IP(), err) + } + if err != nil { - log.Errorf("Error testing: %s", err) - log.Panicf("Please check that %s is publicly reachable at %s/%s", - banner.AppName, gossipAddr.String(), gossipAddr.Network()) + log.Fatalf("Please check that %s is publicly reachable at port %d/%s", + banner.AppName, peering.Port(), peering.Network()) } - _ = conn.Close() - wg.Wait() } diff --git a/plugins/spa/plugin.go b/plugins/spa/plugin.go index 0f63236a74c684b728bd45ffba0564134d211ca7..191b03ebc7d649e4110d0ab7bea63d5cdb431b2a 100644 --- a/plugins/spa/plugin.go +++ b/plugins/spa/plugin.go @@ -1,8 +1,10 @@ package spa import ( + "net" "net/http" "runtime" + "strconv" "sync" "time" @@ -183,9 +185,12 @@ func neighborMetrics() []neighbormetric { break } } + + host := neighbor.Peer.IP().String() + port := neighbor.Peer.Services().Get(service.GossipKey).Port() stats = append(stats, neighbormetric{ ID: neighbor.Peer.ID().String(), - Address: neighbor.Peer.Services().Get(service.GossipKey).String(), + Address: net.JoinHostPort(host, strconv.Itoa(port)), BytesRead: neighbor.BytesRead(), BytesWritten: neighbor.BytesWritten(), ConnectionOrigin: origin, diff --git a/plugins/webapi/getNeighbors/plugin.go b/plugins/webapi/getNeighbors/plugin.go index fe9c397196235d99dde63a7c5b2b467b3965e11e..5f4f45677c361007c3d080bfe19b67552f05c00d 100644 --- a/plugins/webapi/getNeighbors/plugin.go +++ b/plugins/webapi/getNeighbors/plugin.go @@ -2,7 +2,9 @@ package getNeighbors import ( "encoding/base64" + "net" "net/http" + "strconv" "github.com/iotaledger/goshimmer/plugins/autopeering" "github.com/iotaledger/goshimmer/plugins/webapi" @@ -83,12 +85,14 @@ type peerService struct { } func getServices(p *peer.Peer) []peerService { - services := []peerService{} + var services []peerService + + host := p.IP().String() peeringService := p.Services().Get(service.PeeringKey) if peeringService != nil { services = append(services, peerService{ ID: "peering", - Address: peeringService.String(), + Address: net.JoinHostPort(host, strconv.Itoa(peeringService.Port())), }) } @@ -96,7 +100,7 @@ func getServices(p *peer.Peer) []peerService { if gossipService != nil { services = append(services, peerService{ ID: "gossip", - Address: gossipService.String(), + Address: net.JoinHostPort(host, strconv.Itoa(gossipService.Port())), }) } @@ -104,7 +108,7 @@ func getServices(p *peer.Peer) []peerService { if fpcService != nil { services = append(services, peerService{ ID: "FPC", - Address: fpcService.String(), + Address: net.JoinHostPort(host, strconv.Itoa(fpcService.Port())), }) }