mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-10 05:47:59 -05:00
Compare commits
3 Commits
berlintero
...
better-api
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
582aba75c9 | ||
|
|
2ff93d6b27 | ||
|
|
4e19b64b69 |
@@ -2,10 +2,20 @@ load("@prysm//tools/go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["common.go"],
|
||||
srcs = [
|
||||
"common.go",
|
||||
"metrics.go",
|
||||
"types.go",
|
||||
],
|
||||
importpath = "github.com/OffchainLabs/prysm/v6/api/apiutil",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = ["//consensus-types/primitives:go_default_library"],
|
||||
deps = [
|
||||
"//api/server/middleware:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"@com_github_prometheus_client_golang//prometheus:go_default_library",
|
||||
"@com_github_prometheus_client_golang//prometheus/promauto:go_default_library",
|
||||
"@com_github_prometheus_client_golang//prometheus/promhttp:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package rpc
|
||||
package apiutil
|
||||
|
||||
import (
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
61
api/apiutil/types.go
Normal file
61
api/apiutil/types.go
Normal file
@@ -0,0 +1,61 @@
|
||||
package apiutil
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/OffchainLabs/prysm/v6/api/server/middleware"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
)
|
||||
|
||||
type Endpoint struct {
|
||||
Template string
|
||||
Name string
|
||||
Middleware []middleware.Middleware
|
||||
Handler http.HandlerFunc
|
||||
Methods []string
|
||||
}
|
||||
|
||||
func (e *Endpoint) HandlerWithMiddleware() http.HandlerFunc {
|
||||
handler := http.Handler(e.Handler)
|
||||
for _, m := range e.Middleware {
|
||||
handler = m(handler)
|
||||
}
|
||||
|
||||
handler = promhttp.InstrumentHandlerDuration(
|
||||
httpRequestLatency.MustCurryWith(prometheus.Labels{"endpoint": e.Name}),
|
||||
promhttp.InstrumentHandlerCounter(
|
||||
httpRequestCount.MustCurryWith(prometheus.Labels{"endpoint": e.Name}),
|
||||
handler,
|
||||
),
|
||||
)
|
||||
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
// SSE errors are handled separately to avoid interference with the streaming
|
||||
// mechanism and ensure accurate error tracking.
|
||||
if e.Template == "/eth/v1/events" {
|
||||
handler.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
rw := &responseWriter{ResponseWriter: w, statusCode: http.StatusOK}
|
||||
handler.ServeHTTP(rw, r)
|
||||
|
||||
if rw.statusCode >= 400 {
|
||||
httpErrorCount.WithLabelValues(r.URL.Path, http.StatusText(rw.statusCode), r.Method).Inc()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// responseWriter is the wrapper to http Response writer.
|
||||
type responseWriter struct {
|
||||
http.ResponseWriter
|
||||
statusCode int
|
||||
}
|
||||
|
||||
// WriteHeader wraps the WriteHeader method of the underlying http.ResponseWriter to capture the status code.
|
||||
// Refer for WriteHeader doc: https://pkg.go.dev/net/http@go1.23.3#ResponseWriter.
|
||||
func (w *responseWriter) WriteHeader(statusCode int) {
|
||||
w.statusCode = statusCode
|
||||
w.ResponseWriter.WriteHeader(statusCode)
|
||||
}
|
||||
@@ -5,13 +5,13 @@ go_library(
|
||||
srcs = [
|
||||
"endpoints.go",
|
||||
"log.go",
|
||||
"metrics.go",
|
||||
"service.go",
|
||||
],
|
||||
importpath = "github.com/OffchainLabs/prysm/v6/beacon-chain/rpc",
|
||||
visibility = ["//beacon-chain:__subpackages__"],
|
||||
deps = [
|
||||
"//api:go_default_library",
|
||||
"//api/apiutil:go_default_library",
|
||||
"//api/server/middleware:go_default_library",
|
||||
"//beacon-chain/blockchain:go_default_library",
|
||||
"//beacon-chain/builder:go_default_library",
|
||||
@@ -62,9 +62,6 @@ go_library(
|
||||
"@com_github_grpc_ecosystem_go_grpc_middleware//tracing/opentracing:go_default_library",
|
||||
"@com_github_grpc_ecosystem_go_grpc_prometheus//:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_prometheus_client_golang//prometheus:go_default_library",
|
||||
"@com_github_prometheus_client_golang//prometheus/promauto:go_default_library",
|
||||
"@com_github_prometheus_client_golang//prometheus/promhttp:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@io_opentelemetry_go_contrib_instrumentation_google_golang_org_grpc_otelgrpc//:go_default_library",
|
||||
"@org_golang_google_grpc//:go_default_library",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -144,10 +144,10 @@ func Test_endpoints(t *testing.T) {
|
||||
endpoints := s.endpoints(true, nil, nil, nil, nil, nil, nil)
|
||||
actualRoutes := make(map[string][]string, len(endpoints))
|
||||
for _, e := range endpoints {
|
||||
if _, ok := actualRoutes[e.template]; ok {
|
||||
actualRoutes[e.template] = append(actualRoutes[e.template], e.methods...)
|
||||
if _, ok := actualRoutes[e.Template]; ok {
|
||||
actualRoutes[e.Template] = append(actualRoutes[e.Template], e.Methods...)
|
||||
} else {
|
||||
actualRoutes[e.template] = e.methods
|
||||
actualRoutes[e.Template] = e.Methods
|
||||
}
|
||||
}
|
||||
expectedRoutes := make(map[string][]string)
|
||||
|
||||
@@ -14,7 +14,9 @@ go_library(
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//api:go_default_library",
|
||||
"//api/apiutil:go_default_library",
|
||||
"//api/server:go_default_library",
|
||||
"//api/server/middleware:go_default_library",
|
||||
"//api/server/structs:go_default_library",
|
||||
"//beacon-chain/blockchain:go_default_library",
|
||||
"//beacon-chain/cache:go_default_library",
|
||||
@@ -74,6 +76,7 @@ go_test(
|
||||
"handlers_test.go",
|
||||
"handlers_validators_test.go",
|
||||
"init_test.go",
|
||||
"server_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
@@ -128,17 +129,19 @@ func TestListAttestations(t *testing.T) {
|
||||
|
||||
require.NoError(t, s.AttestationsPool.SaveAggregatedAttestations([]ethpbv1alpha1.Att{att1, att2}))
|
||||
require.NoError(t, s.AttestationsPool.SaveUnaggregatedAttestations([]ethpbv1alpha1.Att{att3, att4}))
|
||||
|
||||
ts := startServer(s)
|
||||
defer ts.Close()
|
||||
v1url := ts.URL + "/eth/v1/beacon/pool/attestations"
|
||||
t.Run("empty request", func(t *testing.T) {
|
||||
url := "http://example.com"
|
||||
request := httptest.NewRequest(http.MethodGet, url, nil)
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
url := v1url
|
||||
r, err := http.Get(url)
|
||||
require.NoError(t, err)
|
||||
|
||||
s.ListAttestations(writer, request)
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
assert.Equal(t, http.StatusOK, r.StatusCode)
|
||||
body, err := io.ReadAll(r.Body)
|
||||
require.NoError(t, err)
|
||||
resp := &structs.ListAttestationsResponse{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), &resp))
|
||||
require.NoError(t, json.Unmarshal(body, &resp))
|
||||
require.NotNil(t, resp)
|
||||
require.NotNil(t, resp.Data)
|
||||
|
||||
@@ -147,15 +150,16 @@ func TestListAttestations(t *testing.T) {
|
||||
assert.Equal(t, 4, len(atts))
|
||||
})
|
||||
t.Run("slot request", func(t *testing.T) {
|
||||
url := "http://example.com?slot=2"
|
||||
request := httptest.NewRequest(http.MethodGet, url, nil)
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
url := v1url + "?slot=2"
|
||||
|
||||
s.ListAttestations(writer, request)
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
r, err := http.Get(url)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, http.StatusOK, r.StatusCode)
|
||||
body, err := io.ReadAll(r.Body)
|
||||
require.NoError(t, err)
|
||||
resp := &structs.ListAttestationsResponse{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), &resp))
|
||||
require.NoError(t, json.Unmarshal(body, &resp))
|
||||
require.NotNil(t, resp)
|
||||
require.NotNil(t, resp.Data)
|
||||
|
||||
@@ -167,15 +171,15 @@ func TestListAttestations(t *testing.T) {
|
||||
}
|
||||
})
|
||||
t.Run("index request", func(t *testing.T) {
|
||||
url := "http://example.com?committee_index=4"
|
||||
request := httptest.NewRequest(http.MethodGet, url, nil)
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
url := v1url + "?committee_index=4"
|
||||
r, err := http.Get(url)
|
||||
require.NoError(t, err)
|
||||
|
||||
s.ListAttestations(writer, request)
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
assert.Equal(t, http.StatusOK, r.StatusCode)
|
||||
body, err := io.ReadAll(r.Body)
|
||||
require.NoError(t, err)
|
||||
resp := &structs.ListAttestationsResponse{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), &resp))
|
||||
require.NoError(t, json.Unmarshal(body, &resp))
|
||||
require.NotNil(t, resp)
|
||||
require.NotNil(t, resp.Data)
|
||||
|
||||
@@ -187,15 +191,15 @@ func TestListAttestations(t *testing.T) {
|
||||
}
|
||||
})
|
||||
t.Run("both slot + index request", func(t *testing.T) {
|
||||
url := "http://example.com?slot=2&committee_index=4"
|
||||
request := httptest.NewRequest(http.MethodGet, url, nil)
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
url := v1url + "?slot=2&committee_index=4"
|
||||
r, err := http.Get(url)
|
||||
require.NoError(t, err)
|
||||
|
||||
s.ListAttestations(writer, request)
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
assert.Equal(t, http.StatusOK, r.StatusCode)
|
||||
body, err := io.ReadAll(r.Body)
|
||||
require.NoError(t, err)
|
||||
resp := &structs.ListAttestationsResponse{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), &resp))
|
||||
require.NoError(t, json.Unmarshal(body, &resp))
|
||||
require.NotNil(t, resp)
|
||||
require.NotNil(t, resp.Data)
|
||||
|
||||
@@ -227,16 +231,19 @@ func TestListAttestations(t *testing.T) {
|
||||
|
||||
require.NoError(t, s.AttestationsPool.SaveAggregatedAttestations([]ethpbv1alpha1.Att{att1, att2}))
|
||||
require.NoError(t, s.AttestationsPool.SaveUnaggregatedAttestations([]ethpbv1alpha1.Att{att3, att4}))
|
||||
ts := startServer(s)
|
||||
defer ts.Close()
|
||||
v2url := ts.URL + "/eth/v2/beacon/pool/attestations"
|
||||
t.Run("empty request", func(t *testing.T) {
|
||||
url := "http://example.com"
|
||||
request := httptest.NewRequest(http.MethodGet, url, nil)
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
url := v2url
|
||||
r, err := http.Get(url)
|
||||
require.NoError(t, err)
|
||||
|
||||
s.ListAttestationsV2(writer, request)
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
assert.Equal(t, http.StatusOK, r.StatusCode)
|
||||
body, err := io.ReadAll(r.Body)
|
||||
require.NoError(t, err)
|
||||
resp := &structs.ListAttestationsResponse{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
|
||||
require.NoError(t, json.Unmarshal(body, resp))
|
||||
require.NotNil(t, resp)
|
||||
require.NotNil(t, resp.Data)
|
||||
|
||||
@@ -246,15 +253,15 @@ func TestListAttestations(t *testing.T) {
|
||||
assert.Equal(t, "deneb", resp.Version)
|
||||
})
|
||||
t.Run("slot request", func(t *testing.T) {
|
||||
url := "http://example.com?slot=2"
|
||||
request := httptest.NewRequest(http.MethodGet, url, nil)
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
url := v2url + "?slot=2"
|
||||
r, err := http.Get(url)
|
||||
require.NoError(t, err)
|
||||
|
||||
s.ListAttestationsV2(writer, request)
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
assert.Equal(t, http.StatusOK, r.StatusCode)
|
||||
body, err := io.ReadAll(r.Body)
|
||||
require.NoError(t, err)
|
||||
resp := &structs.ListAttestationsResponse{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
|
||||
require.NoError(t, json.Unmarshal(body, resp))
|
||||
require.NotNil(t, resp)
|
||||
require.NotNil(t, resp.Data)
|
||||
|
||||
@@ -267,15 +274,15 @@ func TestListAttestations(t *testing.T) {
|
||||
}
|
||||
})
|
||||
t.Run("index request", func(t *testing.T) {
|
||||
url := "http://example.com?committee_index=4"
|
||||
request := httptest.NewRequest(http.MethodGet, url, nil)
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
url := v2url + "?committee_index=4"
|
||||
r, err := http.Get(url)
|
||||
require.NoError(t, err)
|
||||
|
||||
s.ListAttestationsV2(writer, request)
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
assert.Equal(t, http.StatusOK, r.StatusCode)
|
||||
body, err := io.ReadAll(r.Body)
|
||||
require.NoError(t, err)
|
||||
resp := &structs.ListAttestationsResponse{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
|
||||
require.NoError(t, json.Unmarshal(body, resp))
|
||||
require.NotNil(t, resp)
|
||||
require.NotNil(t, resp.Data)
|
||||
|
||||
@@ -288,15 +295,15 @@ func TestListAttestations(t *testing.T) {
|
||||
}
|
||||
})
|
||||
t.Run("both slot + index request", func(t *testing.T) {
|
||||
url := "http://example.com?slot=2&committee_index=4"
|
||||
request := httptest.NewRequest(http.MethodGet, url, nil)
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
url := v2url + "?slot=2&committee_index=4"
|
||||
r, err := http.Get(url)
|
||||
require.NoError(t, err)
|
||||
|
||||
s.ListAttestationsV2(writer, request)
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
assert.Equal(t, http.StatusOK, r.StatusCode)
|
||||
body, err := io.ReadAll(r.Body)
|
||||
require.NoError(t, err)
|
||||
resp := &structs.ListAttestationsResponse{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
|
||||
require.NoError(t, json.Unmarshal(body, resp))
|
||||
require.NotNil(t, resp)
|
||||
require.NotNil(t, resp.Data)
|
||||
|
||||
@@ -405,17 +412,19 @@ func TestListAttestations(t *testing.T) {
|
||||
// Added one pre electra attestation to ensure it is ignored.
|
||||
require.NoError(t, s.AttestationsPool.SaveAggregatedAttestations([]ethpbv1alpha1.Att{attElectra1, attElectra2, att1}))
|
||||
require.NoError(t, s.AttestationsPool.SaveUnaggregatedAttestations([]ethpbv1alpha1.Att{attElectra3, attElectra4, att3}))
|
||||
|
||||
ts := startServer(s)
|
||||
defer ts.Close()
|
||||
v2url := ts.URL + "/eth/v2/beacon/pool/attestations"
|
||||
t.Run("empty request", func(t *testing.T) {
|
||||
url := "http://example.com"
|
||||
request := httptest.NewRequest(http.MethodGet, url, nil)
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
url := v2url
|
||||
r, err := http.Get(url)
|
||||
require.NoError(t, err)
|
||||
|
||||
s.ListAttestationsV2(writer, request)
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
assert.Equal(t, http.StatusOK, r.StatusCode)
|
||||
body, err := io.ReadAll(r.Body)
|
||||
require.NoError(t, err)
|
||||
resp := &structs.ListAttestationsResponse{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
|
||||
require.NoError(t, json.Unmarshal(body, resp))
|
||||
require.NotNil(t, resp)
|
||||
require.NotNil(t, resp.Data)
|
||||
|
||||
@@ -425,15 +434,15 @@ func TestListAttestations(t *testing.T) {
|
||||
assert.Equal(t, "electra", resp.Version)
|
||||
})
|
||||
t.Run("slot request", func(t *testing.T) {
|
||||
url := "http://example.com?slot=2"
|
||||
request := httptest.NewRequest(http.MethodGet, url, nil)
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
url := v2url + "?slot=2"
|
||||
r, err := http.Get(url)
|
||||
require.NoError(t, err)
|
||||
|
||||
s.ListAttestationsV2(writer, request)
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
assert.Equal(t, http.StatusOK, r.StatusCode)
|
||||
body, err := io.ReadAll(r.Body)
|
||||
require.NoError(t, err)
|
||||
resp := &structs.ListAttestationsResponse{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
|
||||
require.NoError(t, json.Unmarshal(body, resp))
|
||||
require.NotNil(t, resp)
|
||||
require.NotNil(t, resp.Data)
|
||||
|
||||
@@ -446,15 +455,15 @@ func TestListAttestations(t *testing.T) {
|
||||
}
|
||||
})
|
||||
t.Run("index request", func(t *testing.T) {
|
||||
url := "http://example.com?committee_index=2"
|
||||
request := httptest.NewRequest(http.MethodGet, url, nil)
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
url := v2url + "?committee_index=2"
|
||||
r, err := http.Get(url)
|
||||
require.NoError(t, err)
|
||||
|
||||
s.ListAttestationsV2(writer, request)
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
assert.Equal(t, http.StatusOK, r.StatusCode)
|
||||
body, err := io.ReadAll(r.Body)
|
||||
require.NoError(t, err)
|
||||
resp := &structs.ListAttestationsResponse{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
|
||||
require.NoError(t, json.Unmarshal(body, resp))
|
||||
require.NotNil(t, resp)
|
||||
require.NotNil(t, resp.Data)
|
||||
|
||||
@@ -467,15 +476,15 @@ func TestListAttestations(t *testing.T) {
|
||||
}
|
||||
})
|
||||
t.Run("both slot + index request", func(t *testing.T) {
|
||||
url := "http://example.com?slot=2&committee_index=2"
|
||||
request := httptest.NewRequest(http.MethodGet, url, nil)
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
url := v2url + "?slot=2&committee_index=2"
|
||||
r, err := http.Get(url)
|
||||
require.NoError(t, err)
|
||||
|
||||
s.ListAttestationsV2(writer, request)
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
assert.Equal(t, http.StatusOK, r.StatusCode)
|
||||
body, err := io.ReadAll(r.Body)
|
||||
require.NoError(t, err)
|
||||
resp := &structs.ListAttestationsResponse{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
|
||||
require.NoError(t, json.Unmarshal(body, resp))
|
||||
require.NotNil(t, resp)
|
||||
require.NotNil(t, resp.Data)
|
||||
|
||||
|
||||
@@ -4,6 +4,11 @@
|
||||
package beacon
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/OffchainLabs/prysm/v6/api"
|
||||
"github.com/OffchainLabs/prysm/v6/api/apiutil"
|
||||
"github.com/OffchainLabs/prysm/v6/api/server/middleware"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/blockchain"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/cache"
|
||||
blockfeed "github.com/OffchainLabs/prysm/v6/beacon-chain/core/feed/block"
|
||||
@@ -52,3 +57,399 @@ type Server struct {
|
||||
CoreService *core.Service
|
||||
AttestationStateFetcher blockchain.AttestationStateFetcher
|
||||
}
|
||||
|
||||
func Endpoints(server *Server) []apiutil.Endpoint {
|
||||
const namespace = "beacon"
|
||||
return []apiutil.Endpoint{
|
||||
{
|
||||
Template: "/eth/v1/beacon/states/{state_id}/committees",
|
||||
Name: namespace + ".GetCommittees",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
Handler: server.GetCommittees,
|
||||
Methods: []string{http.MethodGet},
|
||||
},
|
||||
{
|
||||
Template: "/eth/v1/beacon/states/{state_id}/fork",
|
||||
Name: namespace + ".GetStateFork",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
Handler: server.GetStateFork,
|
||||
Methods: []string{http.MethodGet},
|
||||
},
|
||||
{
|
||||
Template: "/eth/v1/beacon/states/{state_id}/root",
|
||||
Name: namespace + ".GetStateRoot",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
Handler: server.GetStateRoot,
|
||||
Methods: []string{http.MethodGet},
|
||||
},
|
||||
{
|
||||
Template: "/eth/v1/beacon/states/{state_id}/sync_committees",
|
||||
Name: namespace + ".GetSyncCommittees",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
Handler: server.GetSyncCommittees,
|
||||
Methods: []string{http.MethodGet},
|
||||
},
|
||||
{
|
||||
Template: "/eth/v1/beacon/states/{state_id}/randao",
|
||||
Name: namespace + ".GetRandao",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
Handler: server.GetRandao,
|
||||
Methods: []string{http.MethodGet},
|
||||
},
|
||||
{
|
||||
// Deprecated: use /eth/v2/beacon/blocks instead
|
||||
Template: "/eth/v1/beacon/blocks",
|
||||
Name: namespace + ".PublishBlock",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.ContentTypeHandler([]string{api.JsonMediaType, api.OctetStreamMediaType}),
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
Handler: server.PublishBlock,
|
||||
Methods: []string{http.MethodPost},
|
||||
},
|
||||
{
|
||||
// Deprecated: use /eth/v2/beacon/blinded_blocks instead
|
||||
Template: "/eth/v1/beacon/blinded_blocks",
|
||||
Name: namespace + ".PublishBlindedBlock",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.ContentTypeHandler([]string{api.JsonMediaType, api.OctetStreamMediaType}),
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
Handler: server.PublishBlindedBlock,
|
||||
Methods: []string{http.MethodPost},
|
||||
},
|
||||
{
|
||||
Template: "/eth/v2/beacon/blocks",
|
||||
Name: namespace + ".PublishBlockV2",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.ContentTypeHandler([]string{api.JsonMediaType, api.OctetStreamMediaType}),
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
Handler: server.PublishBlockV2,
|
||||
Methods: []string{http.MethodPost},
|
||||
},
|
||||
{
|
||||
Template: "/eth/v2/beacon/blinded_blocks",
|
||||
Name: namespace + ".PublishBlindedBlockV2",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.ContentTypeHandler([]string{api.JsonMediaType, api.OctetStreamMediaType}),
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
Handler: server.PublishBlindedBlockV2,
|
||||
Methods: []string{http.MethodPost},
|
||||
},
|
||||
{
|
||||
Template: "/eth/v2/beacon/blocks/{block_id}",
|
||||
Name: namespace + ".GetBlockV2",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType, api.OctetStreamMediaType}),
|
||||
},
|
||||
Handler: server.GetBlockV2,
|
||||
Methods: []string{http.MethodGet},
|
||||
},
|
||||
{
|
||||
// Deprecated: use /eth/v2/beacon/blocks/{block_id}/attestations instead
|
||||
Template: "/eth/v1/beacon/blocks/{block_id}/attestations",
|
||||
Name: namespace + ".GetBlockAttestations",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
Handler: server.GetBlockAttestations,
|
||||
Methods: []string{http.MethodGet},
|
||||
},
|
||||
{
|
||||
Template: "/eth/v2/beacon/blocks/{block_id}/attestations",
|
||||
Name: namespace + ".GetBlockAttestationsV2",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
Handler: server.GetBlockAttestationsV2,
|
||||
Methods: []string{http.MethodGet},
|
||||
},
|
||||
{
|
||||
Template: "/eth/v1/beacon/blinded_blocks/{block_id}",
|
||||
Name: namespace + ".GetBlindedBlock",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType, api.OctetStreamMediaType}),
|
||||
},
|
||||
Handler: server.GetBlindedBlock,
|
||||
Methods: []string{http.MethodGet},
|
||||
},
|
||||
{
|
||||
Template: "/eth/v1/beacon/blocks/{block_id}/root",
|
||||
Name: namespace + ".GetBlockRoot",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
Handler: server.GetBlockRoot,
|
||||
Methods: []string{http.MethodGet},
|
||||
},
|
||||
{
|
||||
// Deprecated: use /eth/v2/beacon/pool/attestations instead
|
||||
Template: "/eth/v1/beacon/pool/attestations",
|
||||
Name: namespace + ".ListAttestations",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
Handler: server.ListAttestations,
|
||||
Methods: []string{http.MethodGet},
|
||||
},
|
||||
{
|
||||
Template: "/eth/v2/beacon/pool/attestations",
|
||||
Name: namespace + ".ListAttestationsV2",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
Handler: server.ListAttestationsV2,
|
||||
Methods: []string{http.MethodGet},
|
||||
},
|
||||
{
|
||||
Template: "/eth/v1/beacon/pool/attestations",
|
||||
Name: namespace + ".SubmitAttestations",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.ContentTypeHandler([]string{api.JsonMediaType}),
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
Handler: server.SubmitAttestations,
|
||||
Methods: []string{http.MethodPost},
|
||||
},
|
||||
{
|
||||
Template: "/eth/v2/beacon/pool/attestations",
|
||||
Name: namespace + ".SubmitAttestationsV2",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.ContentTypeHandler([]string{api.JsonMediaType}),
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
Handler: server.SubmitAttestationsV2,
|
||||
Methods: []string{http.MethodPost},
|
||||
},
|
||||
{
|
||||
Template: "/eth/v1/beacon/pool/voluntary_exits",
|
||||
Name: namespace + ".ListVoluntaryExits",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
Handler: server.ListVoluntaryExits,
|
||||
Methods: []string{http.MethodGet},
|
||||
},
|
||||
{
|
||||
Template: "/eth/v1/beacon/pool/voluntary_exits",
|
||||
Name: namespace + ".SubmitVoluntaryExit",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.ContentTypeHandler([]string{api.JsonMediaType}),
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
Handler: server.SubmitVoluntaryExit,
|
||||
Methods: []string{http.MethodPost},
|
||||
},
|
||||
{
|
||||
Template: "/eth/v1/beacon/pool/sync_committees",
|
||||
Name: namespace + ".SubmitSyncCommitteeSignatures",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.ContentTypeHandler([]string{api.JsonMediaType}),
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
Handler: server.SubmitSyncCommitteeSignatures,
|
||||
Methods: []string{http.MethodPost},
|
||||
},
|
||||
{
|
||||
Template: "/eth/v1/beacon/pool/bls_to_execution_changes",
|
||||
Name: namespace + ".ListBLSToExecutionChanges",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
Handler: server.ListBLSToExecutionChanges,
|
||||
Methods: []string{http.MethodGet},
|
||||
},
|
||||
{
|
||||
Template: "/eth/v1/beacon/pool/bls_to_execution_changes",
|
||||
Name: namespace + ".SubmitBLSToExecutionChanges",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.ContentTypeHandler([]string{api.JsonMediaType}),
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
Handler: server.SubmitBLSToExecutionChanges,
|
||||
Methods: []string{http.MethodPost},
|
||||
},
|
||||
{
|
||||
// Deprecated: use /eth/v2/beacon/pool/attester_slashings instead
|
||||
Template: "/eth/v1/beacon/pool/attester_slashings",
|
||||
Name: namespace + ".GetAttesterSlashings",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
Handler: server.GetAttesterSlashings,
|
||||
Methods: []string{http.MethodGet},
|
||||
},
|
||||
{
|
||||
Template: "/eth/v2/beacon/pool/attester_slashings",
|
||||
Name: namespace + ".GetAttesterSlashingsV2",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
Handler: server.GetAttesterSlashingsV2,
|
||||
Methods: []string{http.MethodGet},
|
||||
},
|
||||
{
|
||||
Template: "/eth/v1/beacon/pool/attester_slashings",
|
||||
Name: namespace + ".SubmitAttesterSlashings",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.ContentTypeHandler([]string{api.JsonMediaType}),
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
Handler: server.SubmitAttesterSlashings,
|
||||
Methods: []string{http.MethodPost},
|
||||
},
|
||||
{
|
||||
Template: "/eth/v2/beacon/pool/attester_slashings",
|
||||
Name: namespace + ".SubmitAttesterSlashingsV2",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.ContentTypeHandler([]string{api.JsonMediaType}),
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
Handler: server.SubmitAttesterSlashingsV2,
|
||||
Methods: []string{http.MethodPost},
|
||||
},
|
||||
{
|
||||
Template: "/eth/v1/beacon/pool/proposer_slashings",
|
||||
Name: namespace + ".GetProposerSlashings",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
Handler: server.GetProposerSlashings,
|
||||
Methods: []string{http.MethodGet},
|
||||
},
|
||||
{
|
||||
Template: "/eth/v1/beacon/pool/proposer_slashings",
|
||||
Name: namespace + ".SubmitProposerSlashing",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.ContentTypeHandler([]string{api.JsonMediaType}),
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
Handler: server.SubmitProposerSlashing,
|
||||
Methods: []string{http.MethodPost},
|
||||
},
|
||||
{
|
||||
Template: "/eth/v1/beacon/headers",
|
||||
Name: namespace + ".GetBlockHeaders",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
Handler: server.GetBlockHeaders,
|
||||
Methods: []string{http.MethodGet},
|
||||
},
|
||||
{
|
||||
Template: "/eth/v1/beacon/headers/{block_id}",
|
||||
Name: namespace + ".GetBlockHeader",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
Handler: server.GetBlockHeader,
|
||||
Methods: []string{http.MethodGet},
|
||||
},
|
||||
{
|
||||
Template: "/eth/v1/beacon/genesis",
|
||||
Name: namespace + ".GetGenesis",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
Handler: server.GetGenesis,
|
||||
Methods: []string{http.MethodGet},
|
||||
},
|
||||
{
|
||||
Template: "/eth/v1/beacon/states/{state_id}/finality_checkpoints",
|
||||
Name: namespace + ".GetFinalityCheckpoints",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
Handler: server.GetFinalityCheckpoints,
|
||||
Methods: []string{http.MethodGet},
|
||||
},
|
||||
{
|
||||
Template: "/eth/v1/beacon/states/{state_id}/validators",
|
||||
Name: namespace + ".GetValidators",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.ContentTypeHandler([]string{api.JsonMediaType}),
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
Handler: server.GetValidators,
|
||||
Methods: []string{http.MethodGet, http.MethodPost},
|
||||
},
|
||||
{
|
||||
Template: "/eth/v1/beacon/states/{state_id}/validators/{validator_id}",
|
||||
Name: namespace + ".GetValidator",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
Handler: server.GetValidator,
|
||||
Methods: []string{http.MethodGet},
|
||||
},
|
||||
{
|
||||
Template: "/eth/v1/beacon/states/{state_id}/validator_balances",
|
||||
Name: namespace + ".GetValidatorBalances",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.ContentTypeHandler([]string{api.JsonMediaType}),
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
Handler: server.GetValidatorBalances,
|
||||
Methods: []string{http.MethodGet, http.MethodPost},
|
||||
},
|
||||
{
|
||||
Template: "/eth/v1/beacon/states/{state_id}/validator_identities",
|
||||
Name: namespace + ".GetValidatorIdentities",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.ContentTypeHandler([]string{api.JsonMediaType}),
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType, api.OctetStreamMediaType}),
|
||||
},
|
||||
Handler: server.GetValidatorIdentities,
|
||||
Methods: []string{http.MethodPost},
|
||||
},
|
||||
{
|
||||
// Deprecated: no longer needed post Electra
|
||||
Template: "/eth/v1/beacon/deposit_snapshot",
|
||||
Name: namespace + ".GetDepositSnapshot",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
Handler: server.GetDepositSnapshot,
|
||||
Methods: []string{http.MethodGet},
|
||||
},
|
||||
{
|
||||
Template: "/eth/v1/beacon/states/{state_id}/pending_deposits",
|
||||
Name: namespace + ".GetPendingDeposits",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
Handler: server.GetPendingDeposits,
|
||||
Methods: []string{http.MethodGet},
|
||||
},
|
||||
{
|
||||
Template: "/eth/v1/beacon/states/{state_id}/pending_consolidations",
|
||||
Name: namespace + ".GetPendingConsolidations",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
Handler: server.GetPendingConsolidations,
|
||||
Methods: []string{http.MethodGet},
|
||||
},
|
||||
{
|
||||
Template: "/eth/v1/beacon/states/{state_id}/pending_partial_withdrawals",
|
||||
Name: namespace + ".GetPendingPartialWithdrawals",
|
||||
Middleware: []middleware.Middleware{
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
Handler: server.GetPendingPartialWithdrawals,
|
||||
Methods: []string{http.MethodGet},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
22
beacon-chain/rpc/eth/beacon/server_test.go
Normal file
22
beacon-chain/rpc/eth/beacon/server_test.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package beacon
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
)
|
||||
|
||||
// Add helper function before test cases
|
||||
func startServer(s *Server) *httptest.Server {
|
||||
router := http.NewServeMux()
|
||||
endpoints := Endpoints(s)
|
||||
for _, e := range endpoints {
|
||||
for i := range e.Methods {
|
||||
router.HandleFunc(
|
||||
fmt.Sprintf("%s %s", e.Methods[i], e.Template),
|
||||
e.HandlerWithMiddleware(),
|
||||
)
|
||||
}
|
||||
}
|
||||
return httptest.NewServer(router)
|
||||
}
|
||||
@@ -296,10 +296,10 @@ func NewService(ctx context.Context, cfg *Config) *Service {
|
||||
|
||||
endpoints := s.endpoints(s.cfg.EnableDebugRPCEndpoints, blocker, stater, rewardFetcher, validatorServer, coreService, ch)
|
||||
for _, e := range endpoints {
|
||||
for i := range e.methods {
|
||||
for i := range e.Methods {
|
||||
s.cfg.Router.HandleFunc(
|
||||
fmt.Sprintf("%s %s", e.methods[i], e.template),
|
||||
e.handlerWithMiddleware(),
|
||||
fmt.Sprintf("%s %s", e.Methods[i], e.Template),
|
||||
e.HandlerWithMiddleware(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
3
changelog/better-api-tests-poc.md
Normal file
3
changelog/better-api-tests-poc.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Ignored
|
||||
|
||||
- Begins the process of improving api unit tests to call a running test server with registered handler instead of testing the handler directly.
|
||||
Reference in New Issue
Block a user