package debug import ( "context" "github.com/golang/protobuf/ptypes/empty" "github.com/libp2p/go-libp2p-core/network" "github.com/libp2p/go-libp2p-core/peer" "github.com/prysmaticlabs/prysm/beacon-chain/p2p" pbrpc "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1" ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) // GetPeer returns the data known about the peer defined by the provided peer id. func (ds *Server) GetPeer(_ context.Context, peerReq *ethpb.PeerRequest) (*pbrpc.DebugPeerResponse, error) { pid, err := peer.Decode(peerReq.PeerId) if err != nil { return nil, status.Errorf(codes.InvalidArgument, "Unable to parse provided peer id: %v", err) } return ds.getPeer(pid) } // ListPeers returns all peers known to the host node, irregardless of if they are connected/ // disconnected. func (ds *Server) ListPeers(_ context.Context, _ *empty.Empty) (*pbrpc.DebugPeerResponses, error) { var responses []*pbrpc.DebugPeerResponse for _, pid := range ds.PeersFetcher.Peers().All() { resp, err := ds.getPeer(pid) if err != nil { return nil, err } responses = append(responses, resp) } return &pbrpc.DebugPeerResponses{Responses: responses}, nil } func (ds *Server) getPeer(pid peer.ID) (*pbrpc.DebugPeerResponse, error) { peers := ds.PeersFetcher.Peers() peerStore := ds.PeerManager.Host().Peerstore() addr, err := peers.Address(pid) if err != nil { return nil, status.Errorf(codes.NotFound, "Requested peer does not exist: %v", err) } dir, err := peers.Direction(pid) if err != nil { return nil, status.Errorf(codes.NotFound, "Requested peer does not exist: %v", err) } pbDirection := ethpb.PeerDirection_UNKNOWN switch dir { case network.DirInbound: pbDirection = ethpb.PeerDirection_INBOUND case network.DirOutbound: pbDirection = ethpb.PeerDirection_OUTBOUND } connState, err := peers.ConnectionState(pid) if err != nil { return nil, status.Errorf(codes.NotFound, "Requested peer does not exist: %v", err) } record, err := peers.ENR(pid) if err != nil { return nil, status.Errorf(codes.NotFound, "Requested peer does not exist: %v", err) } enr := "" if record != nil { enr, err = p2p.SerializeENR(record) if err != nil { return nil, status.Errorf(codes.Internal, "Unable to serialize enr: %v", err) } } metadata, err := peers.Metadata(pid) if err != nil { return nil, status.Errorf(codes.NotFound, "Requested peer does not exist: %v", err) } protocols, err := peerStore.GetProtocols(pid) if err != nil { return nil, status.Errorf(codes.NotFound, "Requested peer does not exist: %v", err) } resp, err := peers.Scorers().BadResponsesScorer().Count(pid) if err != nil { return nil, status.Errorf(codes.NotFound, "Requested peer does not exist: %v", err) } rawPversion, err := peerStore.Get(pid, "ProtocolVersion") pVersion, ok := rawPversion.(string) if err != nil || !ok { pVersion = "" } rawAversion, err := peerStore.Get(pid, "AgentVersion") aVersion, ok := rawAversion.(string) if err != nil || !ok { aVersion = "" } peerInfo := &pbrpc.DebugPeerResponse_PeerInfo{ Protocols: protocols, FaultCount: uint64(resp), ProtocolVersion: pVersion, AgentVersion: aVersion, PeerLatency: uint64(peerStore.LatencyEWMA(pid).Milliseconds()), } if metadata != nil && !metadata.IsNil() { switch { case metadata.MetadataObjV0() != nil: peerInfo.MetadataV0 = metadata.MetadataObjV0() case metadata.MetadataObjV1() != nil: peerInfo.MetadataV1 = metadata.MetadataObjV1() } } addresses := peerStore.Addrs(pid) var stringAddrs []string if addr != nil { stringAddrs = append(stringAddrs, addr.String()) } for _, a := range addresses { // Do not double count address if addr != nil && addr.String() == a.String() { continue } stringAddrs = append(stringAddrs, a.String()) } pStatus, err := peers.ChainState(pid) if err != nil { return nil, status.Errorf(codes.NotFound, "Requested peer does not exist: %v", err) } lastUpdated, err := peers.ChainStateLastUpdated(pid) if err != nil { return nil, status.Errorf(codes.NotFound, "Requested peer does not exist: %v", err) } unixTime := uint64(0) if !lastUpdated.IsZero() { unixTime = uint64(lastUpdated.Unix()) } gScore, bPenalty, topicMaps, err := peers.Scorers().GossipScorer().GossipData(pid) if err != nil { return nil, status.Errorf(codes.NotFound, "Requested peer does not exist: %v", err) } scoreInfo := &pbrpc.ScoreInfo{ OverallScore: float32(peers.Scorers().Score(pid)), ProcessedBlocks: peers.Scorers().BlockProviderScorer().ProcessedBlocks(pid), BlockProviderScore: float32(peers.Scorers().BlockProviderScorer().Score(pid)), TopicScores: topicMaps, GossipScore: float32(gScore), BehaviourPenalty: float32(bPenalty), ValidationError: errorToString(peers.Scorers().ValidationError(pid)), } return &pbrpc.DebugPeerResponse{ ListeningAddresses: stringAddrs, Direction: pbDirection, ConnectionState: ethpb.ConnectionState(connState), PeerId: pid.String(), Enr: enr, PeerInfo: peerInfo, PeerStatus: pStatus, LastUpdated: unixTime, ScoreInfo: scoreInfo, }, nil } func errorToString(err error) string { if err == nil { return "" } return err.Error() }