diff --git a/comm/comm_test.go b/comm/comm_test.go deleted file mode 100644 index a5a8d2471..000000000 --- a/comm/comm_test.go +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright (c) 2018 The VeChainThor developers - -// Distributed under the GNU Lesser General Public License v3.0 software license, see the accompanying -// file LICENSE or - -package comm_test diff --git a/p2psrv/server.go b/p2psrv/server.go index ff64e2ed8..188fd2ce6 100644 --- a/p2psrv/server.go +++ b/p2psrv/server.go @@ -10,6 +10,8 @@ import ( "errors" "math" "net" + "regexp" + "strings" "time" "github.com/ethereum/go-ethereum/common/mclock" @@ -86,7 +88,20 @@ func (s *Server) Start(protocols []*p2p.Protocol, topic discv5.Topic) error { if peer.Inbound() { dir = "inbound" } - log := log.New("peer", peer, "dir", dir) + + if isIncompatible(peer.Name()) { + log.Warn("incompatible peer version", + "name", peer.Name(), + "address", peer.RemoteAddr().String(), + "id", peer.ID().String()) + + peer.Disconnect(p2p.DiscIncompatibleVersion) + s.knownNodes.Remove(peer.ID()) + s.dialingNodes.Remove(peer.ID()) + return nil + } + + log := log.New("peer", peer, "dir", dir, "name", peer.Name()) log.Debug("peer connected") metricConnectedPeers().Add(1) @@ -374,3 +389,19 @@ func (s *Server) fetchBootstrap() { func (s *Server) Options() *Options { return s.opts } + +var versionRegex = regexp.MustCompile(`v\d+\.\d+\.\d+`) + +// isIncompatible checks if the peer is running an incompatible version. +func isIncompatible(peerName string) bool { + // Extract the semantic version from the name + peerVersion := versionRegex.FindString(peerName) + if peerVersion == "" { + return true + } + + major := strings.Split(peerVersion, ".")[0] + + // Only v1 nodes are incompatible for now + return major == "v1" +} diff --git a/p2psrv/server_test.go b/p2psrv/server_test.go index 5cdc45d12..4566c5dcf 100644 --- a/p2psrv/server_test.go +++ b/p2psrv/server_test.go @@ -75,3 +75,38 @@ func TestNewServerConnectOnly(t *testing.T) { assert.True(t, server.discoveredNodes.Contains(knownNode.ID)) assert.True(t, server.knownNodes.Contains(knownNode.ID)) } + +func TestIsIncompatible(t *testing.T) { + testCases := []struct { + peerName string + expected bool + }{ + { + peerName: "thor/v2.1.1-88c7c86-release/linux/go1.21.9", + expected: false, + }, + { + peerName: "thor/v1.1.1-88c7c86-release/linux/go1.21.9", + expected: true, + }, + { + peerName: "thor/v3.1.1-88c7c86-release/linux/go1.21.9", + expected: false, + }, + { + peerName: "", + expected: true, + }, + { + peerName: "thor/v1.bad.v-88c7c86-release/linux/go1.21.9", + expected: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.peerName, func(t *testing.T) { + result := isIncompatible(tc.peerName) + assert.Equal(t, tc.expected, result) + }) + } +}