prysm-pulse/beacon-chain/rpc/eth/node/handlers.go
2023-10-11 22:18:49 +02:00

134 lines
4.4 KiB
Go

package node
import (
"fmt"
"net/http"
"runtime"
"strconv"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/p2p"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/shared"
http2 "github.com/prysmaticlabs/prysm/v4/network/http"
ethpb "github.com/prysmaticlabs/prysm/v4/proto/eth/v1"
"github.com/prysmaticlabs/prysm/v4/runtime/version"
"go.opencensus.io/trace"
)
var (
stateConnecting = ethpb.ConnectionState_CONNECTING.String()
stateConnected = ethpb.ConnectionState_CONNECTED.String()
stateDisconnecting = ethpb.ConnectionState_DISCONNECTING.String()
stateDisconnected = ethpb.ConnectionState_DISCONNECTED.String()
directionInbound = ethpb.PeerDirection_INBOUND.String()
directionOutbound = ethpb.PeerDirection_OUTBOUND.String()
)
// GetSyncStatus requests the beacon node to describe if it's currently syncing or not, and
// if it is, what block it is up to.
func (s *Server) GetSyncStatus(w http.ResponseWriter, r *http.Request) {
ctx, span := trace.StartSpan(r.Context(), "node.GetSyncStatus")
defer span.End()
isOptimistic, err := s.OptimisticModeFetcher.IsOptimistic(ctx)
if err != nil {
http2.HandleError(w, "Could not check optimistic status: "+err.Error(), http.StatusInternalServerError)
return
}
headSlot := s.HeadFetcher.HeadSlot()
response := &SyncStatusResponse{
Data: &SyncStatusResponseData{
HeadSlot: strconv.FormatUint(uint64(headSlot), 10),
SyncDistance: strconv.FormatUint(uint64(s.GenesisTimeFetcher.CurrentSlot()-headSlot), 10),
IsSyncing: s.SyncChecker.Syncing(),
IsOptimistic: isOptimistic,
ElOffline: !s.ExecutionChainInfoFetcher.ExecutionClientConnected(),
},
}
http2.WriteJson(w, response)
}
// GetIdentity retrieves data about the node's network presence.
func (s *Server) GetIdentity(w http.ResponseWriter, r *http.Request) {
_, span := trace.StartSpan(r.Context(), "node.GetIdentity")
defer span.End()
peerId := s.PeerManager.PeerID().String()
sourcep2p := s.PeerManager.Host().Addrs()
p2pAddresses := make([]string, len(sourcep2p))
for i := range sourcep2p {
p2pAddresses[i] = sourcep2p[i].String() + "/p2p/" + peerId
}
sourceDisc, err := s.PeerManager.DiscoveryAddresses()
if err != nil {
http2.HandleError(w, "Could not obtain discovery address: "+err.Error(), http.StatusInternalServerError)
return
}
discoveryAddresses := make([]string, len(sourceDisc))
for i := range sourceDisc {
discoveryAddresses[i] = sourceDisc[i].String()
}
serializedEnr, err := p2p.SerializeENR(s.PeerManager.ENR())
if err != nil {
http2.HandleError(w, "Could not obtain enr: "+err.Error(), http.StatusInternalServerError)
return
}
resp := &GetIdentityResponse{
Data: &Identity{
PeerId: peerId,
Enr: "enr:" + serializedEnr,
P2PAddresses: p2pAddresses,
DiscoveryAddresses: discoveryAddresses,
Metadata: &Metadata{
SeqNumber: strconv.FormatUint(s.MetadataProvider.MetadataSeq(), 10),
Attnets: hexutil.Encode(s.MetadataProvider.Metadata().AttnetsBitfield()),
},
},
}
http2.WriteJson(w, resp)
}
// GetVersion requests that the beacon node identify information about its implementation in a
// format similar to a HTTP User-Agent field.
func (*Server) GetVersion(w http.ResponseWriter, r *http.Request) {
_, span := trace.StartSpan(r.Context(), "node.GetVersion")
defer span.End()
v := fmt.Sprintf("Prysm/%s (%s %s)", version.SemanticVersion(), runtime.GOOS, runtime.GOARCH)
resp := &GetVersionResponse{
Data: &Version{
Version: v,
},
}
http2.WriteJson(w, resp)
}
// GetHealth returns node health status in http status codes. Useful for load balancers.
func (s *Server) GetHealth(w http.ResponseWriter, r *http.Request) {
_, span := trace.StartSpan(r.Context(), "node.GetHealth")
defer span.End()
ok, rawSyncingStatus, syncingStatus := shared.UintFromQuery(w, r, "syncing_status")
// lint:ignore uintcast -- custom syncing status being outside of range is harmless
intSyncingStatus := int(syncingStatus)
if !ok || (rawSyncingStatus != "" && http.StatusText(intSyncingStatus) == "") {
http2.HandleError(w, "syncing_status is not a valid HTTP status code", http.StatusBadRequest)
return
}
if s.SyncChecker.Synced() {
return
}
if s.SyncChecker.Syncing() || s.SyncChecker.Initialized() {
if rawSyncingStatus != "" {
w.WriteHeader(intSyncingStatus)
} else {
w.WriteHeader(http.StatusPartialContent)
}
return
}
w.WriteHeader(http.StatusServiceUnavailable)
}