Update Beacon API to v2.1.0 (#9797)

* `Eth-Consensus-Version` header

* rename unused receiver

* omit receiver name

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
This commit is contained in:
Radosław Kapka
2021-10-18 20:55:18 +02:00
committed by GitHub
parent cf956c718d
commit 7b8aedbfe4
3 changed files with 68 additions and 18 deletions

View File

@@ -96,12 +96,12 @@ func handleGetSSZ(
apimiddleware.WriteError(w, errJson, nil)
return true
}
responseSsz, errJson := serializeMiddlewareResponseIntoSSZ(config.responseJson.SSZData())
respVersion, responseSsz, errJson := serializeMiddlewareResponseIntoSSZ(config.responseJson)
if errJson != nil {
apimiddleware.WriteError(w, errJson, nil)
return true
}
if errJson := writeSSZResponseHeaderAndBody(grpcResponse, w, responseSsz, config.fileName); errJson != nil {
if errJson := writeSSZResponseHeaderAndBody(grpcResponse, w, responseSsz, respVersion, config.fileName); errJson != nil {
apimiddleware.WriteError(w, errJson, nil)
return true
}
@@ -143,16 +143,16 @@ func prepareSSZRequestForProxying(
return nil
}
func serializeMiddlewareResponseIntoSSZ(data string) (sszResponse []byte, errJson apimiddleware.ErrorJson) {
func serializeMiddlewareResponseIntoSSZ(respJson sszResponseJson) (version string, ssz []byte, errJson apimiddleware.ErrorJson) {
// Serialize the SSZ part of the deserialized value.
b, err := base64.StdEncoding.DecodeString(data)
data, err := base64.StdEncoding.DecodeString(respJson.SSZData())
if err != nil {
return nil, apimiddleware.InternalServerErrorWithMessage(err, "could not decode response body into base64")
return "", nil, apimiddleware.InternalServerErrorWithMessage(err, "could not decode response body into base64")
}
return b, nil
return strings.ToLower(respJson.SSZVersion()), data, nil
}
func writeSSZResponseHeaderAndBody(grpcResp *http.Response, w http.ResponseWriter, responseSsz []byte, fileName string) apimiddleware.ErrorJson {
func writeSSZResponseHeaderAndBody(grpcResp *http.Response, w http.ResponseWriter, respSsz []byte, respVersion, fileName string) apimiddleware.ErrorJson {
var statusCodeHeader string
for h, vs := range grpcResp.Header {
// We don't want to expose any gRPC metadata in the HTTP response, so we skip forwarding metadata headers.
@@ -166,6 +166,10 @@ func writeSSZResponseHeaderAndBody(grpcResp *http.Response, w http.ResponseWrite
}
}
}
w.Header().Set("Content-Length", strconv.Itoa(len(respSsz)))
w.Header().Set("Content-Type", "application/octet-stream")
w.Header().Set("Content-Disposition", "attachment; filename="+fileName)
w.Header().Set("Eth-Consensus-Version", respVersion)
if statusCodeHeader != "" {
code, err := strconv.Atoi(statusCodeHeader)
if err != nil {
@@ -175,10 +179,7 @@ func writeSSZResponseHeaderAndBody(grpcResp *http.Response, w http.ResponseWrite
} else {
w.WriteHeader(grpcResp.StatusCode)
}
w.Header().Set("Content-Length", strconv.Itoa(len(responseSsz)))
w.Header().Set("Content-Type", "application/octet-stream")
w.Header().Set("Content-Disposition", "attachment; filename="+fileName)
if _, err := io.Copy(w, ioutil.NopCloser(bytes.NewReader(responseSsz))); err != nil {
if _, err := io.Copy(w, ioutil.NopCloser(bytes.NewReader(respSsz))); err != nil {
return apimiddleware.InternalServerErrorWithMessage(err, "could not write response message")
}
return nil

View File

@@ -18,6 +18,19 @@ import (
"github.com/r3labs/sse"
)
type testSSZResponseJson struct {
Version string `json:"version"`
Data string `json:"data"`
}
func (t testSSZResponseJson) SSZVersion() string {
return t.Version
}
func (t testSSZResponseJson) SSZData() string {
return t.Data
}
func TestSSZRequested(t *testing.T) {
t.Run("ssz_requested", func(t *testing.T) {
request := httptest.NewRequest("GET", "http://foo.example", nil)
@@ -64,13 +77,22 @@ func TestPrepareSSZRequestForProxying(t *testing.T) {
func TestSerializeMiddlewareResponseIntoSSZ(t *testing.T) {
t.Run("ok", func(t *testing.T) {
ssz, errJson := serializeMiddlewareResponseIntoSSZ("Zm9v")
j := testSSZResponseJson{
Version: "Version",
Data: "Zm9v",
}
v, ssz, errJson := serializeMiddlewareResponseIntoSSZ(j)
require.Equal(t, true, errJson == nil)
assert.DeepEqual(t, []byte("foo"), ssz)
assert.Equal(t, "version", v)
})
t.Run("invalid_data", func(t *testing.T) {
_, errJson := serializeMiddlewareResponseIntoSSZ("invalid")
j := testSSZResponseJson{
Version: "Version",
Data: "invalid",
}
_, _, errJson := serializeMiddlewareResponseIntoSSZ(j)
require.Equal(t, false, errJson == nil)
assert.Equal(t, true, strings.Contains(errJson.Msg(), "could not decode response body into base64"))
assert.Equal(t, http.StatusInternalServerError, errJson.StatusCode())
@@ -78,6 +100,10 @@ func TestSerializeMiddlewareResponseIntoSSZ(t *testing.T) {
}
func TestWriteSSZResponseHeaderAndBody(t *testing.T) {
responseSsz := []byte("ssz")
version := "version"
fileName := "test.ssz"
t.Run("ok", func(t *testing.T) {
response := &http.Response{
Header: http.Header{
@@ -85,11 +111,11 @@ func TestWriteSSZResponseHeaderAndBody(t *testing.T) {
"Grpc-Metadata-" + grpc.HttpCodeMetadataKey: []string{"204"},
},
}
responseSsz := []byte("ssz")
writer := httptest.NewRecorder()
writer.Body = &bytes.Buffer{}
errJson := writeSSZResponseHeaderAndBody(response, writer, responseSsz, "test.ssz")
errJson := writeSSZResponseHeaderAndBody(response, writer, responseSsz, version, fileName)
require.Equal(t, true, errJson == nil)
v, ok := writer.Header()["Foo"]
require.Equal(t, true, ok, "header not found")
@@ -107,6 +133,10 @@ func TestWriteSSZResponseHeaderAndBody(t *testing.T) {
require.Equal(t, true, ok, "header not found")
require.Equal(t, 1, len(v), "wrong number of header values")
assert.Equal(t, "attachment; filename=test.ssz", v[0])
v, ok = writer.Header()["Eth-Consensus-Version"]
require.Equal(t, true, ok, "header not found")
require.Equal(t, 1, len(v), "wrong number of header values")
assert.Equal(t, "version", v[0])
assert.Equal(t, 204, writer.Code)
})
@@ -115,11 +145,10 @@ func TestWriteSSZResponseHeaderAndBody(t *testing.T) {
Header: http.Header{},
StatusCode: 204,
}
responseSsz := []byte("ssz")
writer := httptest.NewRecorder()
writer.Body = &bytes.Buffer{}
errJson := writeSSZResponseHeaderAndBody(response, writer, responseSsz, "test.ssz")
errJson := writeSSZResponseHeaderAndBody(response, writer, responseSsz, version, fileName)
require.Equal(t, true, errJson == nil)
assert.Equal(t, 204, writer.Code)
})
@@ -135,7 +164,7 @@ func TestWriteSSZResponseHeaderAndBody(t *testing.T) {
writer := httptest.NewRecorder()
writer.Body = &bytes.Buffer{}
errJson := writeSSZResponseHeaderAndBody(response, writer, responseSsz, "test.ssz")
errJson := writeSSZResponseHeaderAndBody(response, writer, responseSsz, version, fileName)
require.Equal(t, false, errJson == nil)
assert.Equal(t, true, strings.Contains(errJson.Msg(), "could not parse status code"))
assert.Equal(t, http.StatusInternalServerError, errJson.StatusCode())

View File

@@ -1,7 +1,10 @@
package apimiddleware
import (
"strings"
"github.com/prysmaticlabs/prysm/api/gateway/apimiddleware"
ethpbv2 "github.com/prysmaticlabs/prysm/proto/eth/v2"
)
// genesisResponseJson is used in /beacon/genesis API endpoint.
@@ -656,6 +659,7 @@ type syncCommitteeContributionJson struct {
// sszResponseJson is a common abstraction over all SSZ responses.
type sszResponseJson interface {
SSZVersion() string
SSZData() string
}
@@ -668,6 +672,10 @@ func (ssz *blockSSZResponseJson) SSZData() string {
return ssz.Data
}
func (*blockSSZResponseJson) SSZVersion() string {
return strings.ToLower(ethpbv2.Version_PHASE0.String())
}
// blockSSZResponseV2Json is used in /v2/beacon/blocks/{block_id} API endpoint.
type blockSSZResponseV2Json struct {
Version string `json:"version"`
@@ -678,6 +686,10 @@ func (ssz *blockSSZResponseV2Json) SSZData() string {
return ssz.Data
}
func (ssz *blockSSZResponseV2Json) SSZVersion() string {
return ssz.Version
}
// beaconStateSSZResponseJson is used in /debug/beacon/states/{state_id} API endpoint.
type beaconStateSSZResponseJson struct {
Data string `json:"data"`
@@ -687,6 +699,10 @@ func (ssz *beaconStateSSZResponseJson) SSZData() string {
return ssz.Data
}
func (*beaconStateSSZResponseJson) SSZVersion() string {
return strings.ToLower(ethpbv2.Version_PHASE0.String())
}
// beaconStateSSZResponseV2Json is used in /v2/debug/beacon/states/{state_id} API endpoint.
type beaconStateSSZResponseV2Json struct {
Version string `json:"version"`
@@ -697,6 +713,10 @@ func (ssz *beaconStateSSZResponseV2Json) SSZData() string {
return ssz.Data
}
func (ssz *beaconStateSSZResponseV2Json) SSZVersion() string {
return ssz.Version
}
// ---------------
// Events.
// ---------------