Skip to content

Commit

Permalink
extend getpeers method
Browse files Browse the repository at this point in the history
Signed-off-by: Brett Rhodes <[email protected]>
  • Loading branch information
EdgeDLT committed Jun 17, 2024
1 parent cf4d4a2 commit 14d20c8
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 18 deletions.
7 changes: 6 additions & 1 deletion docs/rpc.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,14 +199,19 @@ enabled in the server's protocol configuration.

##### `traverseiterator` and `terminatesession`

NeoGo returns an error when it is unable to find a session or iterator, unlike
NeoGo returns an error when it is unable to find a session or iterator, unlike
the error-free C# response that provides a default result.

##### `verifyProof`

NeoGo can generate an error in response to an invalid proof, unlike
the error-free C# implementation.

##### `getPeers`

NeoGo extends the `getpeers` RPC call to return the user agent and
last known block height for each connected peer where available.

### Unsupported methods

Methods listed below are not going to be supported for various reasons
Expand Down
96 changes: 89 additions & 7 deletions pkg/neorpc/result/peers.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import (
type (
// GetPeers payload for outputting peers in `getpeers` RPC call.
GetPeers struct {
Unconnected Peers `json:"unconnected"`
Connected Peers `json:"connected"`
Bad Peers `json:"bad"`
Unconnected Peers `json:"unconnected"`
Connected ConnectedPeers `json:"connected"`
Bad Peers `json:"bad"`
}

// Peers represents a slice of peers.
Expand All @@ -22,13 +22,24 @@ type (
Address string `json:"address"`
Port uint16 `json:"port"`
}

// ConnectedPeers represents a slice of connected peers.
ConnectedPeers []ConnectedPeer

// ConnectedPeer represents a connected peer.
ConnectedPeer struct {
Address string `json:"address"`
Port uint16 `json:"port"`
UserAgent string `json:"useragent,omitempty"`
LastKnownHeight uint32 `json:"lastknownheight,omitempty"`
}
)

// NewGetPeers creates a new GetPeers structure.
func NewGetPeers() GetPeers {
return GetPeers{
Unconnected: []Peer{},
Connected: []Peer{},
Connected: []ConnectedPeer{},
Bad: []Peer{},
}
}
Expand All @@ -38,9 +49,13 @@ func (g *GetPeers) AddUnconnected(addrs []string) {
g.Unconnected.addPeers(addrs)
}

// AddConnected adds a set of peers to the connected peers slice.
func (g *GetPeers) AddConnected(addrs []string) {
g.Connected.addPeers(addrs)
// AddConnected adds a set of connected peers to the connected peers slice.
func (g *GetPeers) AddConnected(connectedPeers []struct {
Address string
UserAgent string
Height uint32
}) {
g.Connected.addConnectedPeers(connectedPeers)
}

// AddBad adds a set of peers to the bad peers slice.
Expand Down Expand Up @@ -68,6 +83,32 @@ func (p *Peers) addPeers(addrs []string) {
}
}

// addConnectedPeers adds a set of connected peers to the given connected peer slice.
func (c *ConnectedPeers) addConnectedPeers(connectedPeers []struct {
Address string
UserAgent string
Height uint32
}) {
for i := range connectedPeers {
host, portStr, err := net.SplitHostPort(connectedPeers[i].Address)
if err != nil {
continue
}
port, err := strconv.ParseUint(portStr, 10, 16)
if err != nil {
port = 0
}
peer := ConnectedPeer{
Address: host,
Port: uint16(port),
UserAgent: connectedPeers[i].UserAgent,
LastKnownHeight: connectedPeers[i].Height,
}

*c = append(*c, peer)
}
}

func (p *Peer) UnmarshalJSON(data []byte) error {
type NewPeer Peer
var np NewPeer
Expand Down Expand Up @@ -98,3 +139,44 @@ func (p *Peer) UnmarshalJSON(data []byte) error {
}
return err
}

func (cp *ConnectedPeer) UnmarshalJSON(data []byte) error {
type Alias ConnectedPeer
var alias Alias

err := json.Unmarshal(data, &alias)
if err == nil {
*cp = ConnectedPeer(alias)
return nil
}

type OldConnectedPeer struct {
Address string `json:"address"`
Port string `json:"port"`
UserAgent string `json:"useragent,omitempty"`
Height string `json:"lastknownheight,omitempty"`
}
var old OldConnectedPeer

err = json.Unmarshal(data, &old)
if err == nil {
port, err := strconv.ParseUint(old.Port, 10, 16)
if err != nil {
return err
}
height, err := strconv.ParseUint(old.Height, 10, 32)
if err != nil {
height = 0
}

*cp = ConnectedPeer{
Address: old.Address,
Port: uint16(port),
UserAgent: old.UserAgent,
LastKnownHeight: uint32(height),
}
return nil
}

return err
}
16 changes: 14 additions & 2 deletions pkg/neorpc/result/peers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,27 @@ func TestGetPeers(t *testing.T) {

gp.AddUnconnected([]string{"1.1.1.1:53", "8.8.8.8:53", "9.9.9.9:53"})
unsupportedFormat := "2001:DB0:0:123A:::30"
gp.AddConnected([]string{"192.168.0.1:10333", unsupportedFormat, "[2001:DB0:0:123A::]:30"})
gp.AddConnected([]struct {
Address string
UserAgent string
Height uint32
}{
{"192.168.0.1:10333", "/NEO-GO:0.106.2/", 100},
{unsupportedFormat, "", 0},
{"[2001:DB0:0:123A::]:30", "/NEO-GO:0.106.2/", 200},
})
gp.AddBad([]string{"127.0.0.1:20333", "127.0.0.1:65536"})

require.Equal(t, 3, len(gp.Unconnected))
require.Equal(t, 2, len(gp.Connected))
require.Equal(t, 2, len(gp.Bad))
require.Equal(t, "192.168.0.1", gp.Connected[0].Address)
require.Equal(t, uint16(10333), gp.Connected[0].Port)
require.Equal(t, "/NEO-GO:0.106.2/", gp.Connected[0].UserAgent)
require.Equal(t, uint32(100), gp.Connected[0].LastKnownHeight)
require.Equal(t, uint16(30), gp.Connected[1].Port)
require.Equal(t, "/NEO-GO:0.106.2/", gp.Connected[1].UserAgent)
require.Equal(t, uint32(200), gp.Connected[1].LastKnownHeight)
require.Equal(t, "127.0.0.1", gp.Bad[0].Address)
require.Equal(t, uint16(20333), gp.Bad[0].Port)
require.Equal(t, uint16(0), gp.Bad[1].Port)
Expand All @@ -32,7 +44,7 @@ func TestGetPeers(t *testing.T) {
oldPeerFormat := `{"unconnected": [{"address": "20.109.188.128","port": "10333"},{"address": "27.188.182.47","port": "10333"}],"connected": [{"address": "54.227.43.72","port": "10333"},{"address": "157.90.177.38","port": "10333"}],"bad": [{"address": "5.226.142.226","port": "10333"}]}`
err := json.Unmarshal([]byte(oldPeerFormat), &gps)
require.NoError(t, err)
newPeerFormat := `{"unconnected": [{"address": "20.109.188.128","port": 10333},{"address": "27.188.182.47","port": 10333}],"connected": [{"address": "54.227.43.72","port": 10333},{"address": "157.90.177.38","port": 10333}],"bad": [{"address": "5.226.142.226","port": 10333},{"address": "54.208.117.178","port": 10333}]}`
newPeerFormat := `{"unconnected": [{"address": "20.109.188.128","port": 10333},{"address": "27.188.182.47","port": 10333}],"connected": [{"address": "54.227.43.72","port": 10333,"useragent": "/NEO-GO:0.106.2/","lastknownheight": 100},{"address": "157.90.177.38","port": 10333,"useragent": "/NEO-GO:0.106.2/","lastknownheight": 100}],"bad": [{"address": "5.226.142.226","port": 10333},{"address": "54.208.117.178","port": 10333}]}`
err = json.Unmarshal([]byte(newPeerFormat), &gps)
require.NoError(t, err)
badIntFormat := `{"unconnected": [{"address": "20.109.188.128","port": 65536}],"connected": [],"bad": []}`
Expand Down
24 changes: 20 additions & 4 deletions pkg/network/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -427,15 +427,31 @@ func (s *Server) BadPeers() []string {
}

// ConnectedPeers returns a list of currently connected peers.
func (s *Server) ConnectedPeers() []string {
func (s *Server) ConnectedPeers() []struct {
Address string
UserAgent string
Height uint32
} {
s.lock.RLock()
defer s.lock.RUnlock()

peers := make([]string, 0, len(s.peers))
peers := make([]struct {
Address string
UserAgent string
Height uint32
}, 0, len(s.peers))

for k := range s.peers {
peers = append(peers, k.PeerAddr().String())
peers = append(peers, struct {
Address string
UserAgent string
Height uint32
}{
Address: k.PeerAddr().String(),
UserAgent: string(k.Version().UserAgent),
Height: k.LastBlockIndex(),
})
}

return peers
}

Expand Down
8 changes: 5 additions & 3 deletions pkg/rpcclient/rpc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -578,10 +578,12 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
Port: 20333,
},
},
Connected: result.Peers{
Connected: result.ConnectedPeers{
{
Address: "127.0.0.1",
Port: 20335,
Address: "127.0.0.1",
Port: 20335,
UserAgent: "/NEO-GO:0.106.2/",
LastKnownHeight: 1000,
},
},
Bad: result.Peers{
Expand Down
2 changes: 1 addition & 1 deletion pkg/services/rpcsrv/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1210,7 +1210,7 @@ var rpcTestCases = map[string][]rpcTestCase{
result: func(*executor) any {
return &result.GetPeers{
Unconnected: []result.Peer{},
Connected: []result.Peer{},
Connected: []result.ConnectedPeer{},
Bad: []result.Peer{},
}
},
Expand Down

0 comments on commit 14d20c8

Please sign in to comment.