mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 15:37:56 -05:00
Publish blockv2 ssz (#12636)
* wip produce block v2 ssz * adding functions for ssz processing * fixing linting * Update beacon-chain/rpc/eth/beacon/handlers.go Co-authored-by: Radosław Kapka <rkapka@wp.pl> * addressing review feedback * fixing linting --------- Co-authored-by: Radosław Kapka <rkapka@wp.pl>
This commit is contained in:
@@ -15,6 +15,9 @@ import (
|
|||||||
"github.com/prysmaticlabs/prysm/v4/consensus-types/blocks"
|
"github.com/prysmaticlabs/prysm/v4/consensus-types/blocks"
|
||||||
"github.com/prysmaticlabs/prysm/v4/consensus-types/interfaces"
|
"github.com/prysmaticlabs/prysm/v4/consensus-types/interfaces"
|
||||||
"github.com/prysmaticlabs/prysm/v4/network"
|
"github.com/prysmaticlabs/prysm/v4/network"
|
||||||
|
ethpbv1 "github.com/prysmaticlabs/prysm/v4/proto/eth/v1"
|
||||||
|
ethpbv2 "github.com/prysmaticlabs/prysm/v4/proto/eth/v2"
|
||||||
|
"github.com/prysmaticlabs/prysm/v4/proto/migration"
|
||||||
eth "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
|
eth "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -38,7 +41,142 @@ func (bs *Server) PublishBlindedBlockV2(w http.ResponseWriter, r *http.Request)
|
|||||||
if ok := bs.checkSync(r.Context(), w); !ok {
|
if ok := bs.checkSync(r.Context(), w); !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
isSSZ, err := network.SszRequested(r)
|
||||||
|
if isSSZ && err == nil {
|
||||||
|
publishBlindedBlockV2SSZ(bs, w, r)
|
||||||
|
} else {
|
||||||
|
publishBlindedBlockV2(bs, w, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func publishBlindedBlockV2SSZ(bs *Server, w http.ResponseWriter, r *http.Request) {
|
||||||
|
body, err := io.ReadAll(r.Body)
|
||||||
|
if err != nil {
|
||||||
|
errJson := &network.DefaultErrorJson{
|
||||||
|
Message: "Could not read request body: " + err.Error(),
|
||||||
|
Code: http.StatusInternalServerError,
|
||||||
|
}
|
||||||
|
network.WriteError(w, errJson)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
capellaBlock := ðpbv2.SignedBlindedBeaconBlockCapella{}
|
||||||
|
if err := capellaBlock.UnmarshalSSZ(body); err == nil {
|
||||||
|
v1block, err := migration.BlindedCapellaToV1Alpha1SignedBlock(capellaBlock)
|
||||||
|
if err != nil {
|
||||||
|
errJson := &network.DefaultErrorJson{
|
||||||
|
Message: "Could not decode request body into consensus block: " + err.Error(),
|
||||||
|
Code: http.StatusBadRequest,
|
||||||
|
}
|
||||||
|
network.WriteError(w, errJson)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
genericBlock := ð.GenericSignedBeaconBlock{
|
||||||
|
Block: ð.GenericSignedBeaconBlock_BlindedCapella{
|
||||||
|
BlindedCapella: v1block,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if err = bs.validateBroadcast(r, genericBlock); err != nil {
|
||||||
|
errJson := &network.DefaultErrorJson{
|
||||||
|
Message: err.Error(),
|
||||||
|
Code: http.StatusBadRequest,
|
||||||
|
}
|
||||||
|
network.WriteError(w, errJson)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
bs.proposeBlock(r.Context(), w, genericBlock)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
bellatrixBlock := ðpbv2.SignedBlindedBeaconBlockBellatrix{}
|
||||||
|
if err := bellatrixBlock.UnmarshalSSZ(body); err == nil {
|
||||||
|
v1block, err := migration.BlindedBellatrixToV1Alpha1SignedBlock(bellatrixBlock)
|
||||||
|
if err != nil {
|
||||||
|
errJson := &network.DefaultErrorJson{
|
||||||
|
Message: "Could not decode request body into consensus block: " + err.Error(),
|
||||||
|
Code: http.StatusBadRequest,
|
||||||
|
}
|
||||||
|
network.WriteError(w, errJson)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
genericBlock := ð.GenericSignedBeaconBlock{
|
||||||
|
Block: ð.GenericSignedBeaconBlock_BlindedBellatrix{
|
||||||
|
BlindedBellatrix: v1block,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if err = bs.validateBroadcast(r, genericBlock); err != nil {
|
||||||
|
errJson := &network.DefaultErrorJson{
|
||||||
|
Message: err.Error(),
|
||||||
|
Code: http.StatusBadRequest,
|
||||||
|
}
|
||||||
|
network.WriteError(w, errJson)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
bs.proposeBlock(r.Context(), w, genericBlock)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// blinded is not supported before bellatrix hardfork
|
||||||
|
altairBlock := ðpbv2.SignedBeaconBlockAltair{}
|
||||||
|
if err := altairBlock.UnmarshalSSZ(body); err == nil {
|
||||||
|
v1block, err := migration.AltairToV1Alpha1SignedBlock(altairBlock)
|
||||||
|
if err != nil {
|
||||||
|
errJson := &network.DefaultErrorJson{
|
||||||
|
Message: "Could not decode request body into consensus block: " + err.Error(),
|
||||||
|
Code: http.StatusBadRequest,
|
||||||
|
}
|
||||||
|
network.WriteError(w, errJson)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
genericBlock := ð.GenericSignedBeaconBlock{
|
||||||
|
Block: ð.GenericSignedBeaconBlock_Altair{
|
||||||
|
Altair: v1block,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if err = bs.validateBroadcast(r, genericBlock); err != nil {
|
||||||
|
errJson := &network.DefaultErrorJson{
|
||||||
|
Message: err.Error(),
|
||||||
|
Code: http.StatusBadRequest,
|
||||||
|
}
|
||||||
|
network.WriteError(w, errJson)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
bs.proposeBlock(r.Context(), w, genericBlock)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
phase0Block := ðpbv1.SignedBeaconBlock{}
|
||||||
|
if err := phase0Block.UnmarshalSSZ(body); err == nil {
|
||||||
|
v1block, err := migration.V1ToV1Alpha1SignedBlock(phase0Block)
|
||||||
|
if err != nil {
|
||||||
|
errJson := &network.DefaultErrorJson{
|
||||||
|
Message: "Could not decode request body into consensus block: " + err.Error(),
|
||||||
|
Code: http.StatusBadRequest,
|
||||||
|
}
|
||||||
|
network.WriteError(w, errJson)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
genericBlock := ð.GenericSignedBeaconBlock{
|
||||||
|
Block: ð.GenericSignedBeaconBlock_Phase0{
|
||||||
|
Phase0: v1block,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if err = bs.validateBroadcast(r, genericBlock); err != nil {
|
||||||
|
errJson := &network.DefaultErrorJson{
|
||||||
|
Message: err.Error(),
|
||||||
|
Code: http.StatusBadRequest,
|
||||||
|
}
|
||||||
|
network.WriteError(w, errJson)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
bs.proposeBlock(r.Context(), w, genericBlock)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
errJson := &network.DefaultErrorJson{
|
||||||
|
Message: "Body does not represent a valid block type",
|
||||||
|
Code: http.StatusBadRequest,
|
||||||
|
}
|
||||||
|
network.WriteError(w, errJson)
|
||||||
|
}
|
||||||
|
|
||||||
|
func publishBlindedBlockV2(bs *Server, w http.ResponseWriter, r *http.Request) {
|
||||||
validate := validator.New()
|
validate := validator.New()
|
||||||
body, err := io.ReadAll(r.Body)
|
body, err := io.ReadAll(r.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -167,7 +305,15 @@ func (bs *Server) PublishBlockV2(w http.ResponseWriter, r *http.Request) {
|
|||||||
if ok := bs.checkSync(r.Context(), w); !ok {
|
if ok := bs.checkSync(r.Context(), w); !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
isSSZ, err := network.SszRequested(r)
|
||||||
|
if isSSZ && err == nil {
|
||||||
|
publishBlockV2SSZ(bs, w, r)
|
||||||
|
} else {
|
||||||
|
publishBlockV2(bs, w, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func publishBlockV2SSZ(bs *Server, w http.ResponseWriter, r *http.Request) {
|
||||||
validate := validator.New()
|
validate := validator.New()
|
||||||
body, err := io.ReadAll(r.Body)
|
body, err := io.ReadAll(r.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -178,7 +324,140 @@ func (bs *Server) PublishBlockV2(w http.ResponseWriter, r *http.Request) {
|
|||||||
network.WriteError(w, errJson)
|
network.WriteError(w, errJson)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
capellaBlock := ðpbv2.SignedBeaconBlockCapella{}
|
||||||
|
if err := capellaBlock.UnmarshalSSZ(body); err == nil {
|
||||||
|
if err = validate.Struct(capellaBlock); err == nil {
|
||||||
|
v1block, err := migration.CapellaToV1Alpha1SignedBlock(capellaBlock)
|
||||||
|
if err != nil {
|
||||||
|
errJson := &network.DefaultErrorJson{
|
||||||
|
Message: "Could not decode request body into consensus block: " + err.Error(),
|
||||||
|
Code: http.StatusBadRequest,
|
||||||
|
}
|
||||||
|
network.WriteError(w, errJson)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
genericBlock := ð.GenericSignedBeaconBlock{
|
||||||
|
Block: ð.GenericSignedBeaconBlock_Capella{
|
||||||
|
Capella: v1block,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if err = bs.validateBroadcast(r, genericBlock); err != nil {
|
||||||
|
errJson := &network.DefaultErrorJson{
|
||||||
|
Message: err.Error(),
|
||||||
|
Code: http.StatusBadRequest,
|
||||||
|
}
|
||||||
|
network.WriteError(w, errJson)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
bs.proposeBlock(r.Context(), w, genericBlock)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bellatrixBlock := ðpbv2.SignedBeaconBlockBellatrix{}
|
||||||
|
if err := bellatrixBlock.UnmarshalSSZ(body); err == nil {
|
||||||
|
if err = validate.Struct(bellatrixBlock); err == nil {
|
||||||
|
v1block, err := migration.BellatrixToV1Alpha1SignedBlock(bellatrixBlock)
|
||||||
|
if err != nil {
|
||||||
|
errJson := &network.DefaultErrorJson{
|
||||||
|
Message: "Could not decode request body into consensus block: " + err.Error(),
|
||||||
|
Code: http.StatusBadRequest,
|
||||||
|
}
|
||||||
|
network.WriteError(w, errJson)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
genericBlock := ð.GenericSignedBeaconBlock{
|
||||||
|
Block: ð.GenericSignedBeaconBlock_Bellatrix{
|
||||||
|
Bellatrix: v1block,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if err = bs.validateBroadcast(r, genericBlock); err != nil {
|
||||||
|
errJson := &network.DefaultErrorJson{
|
||||||
|
Message: err.Error(),
|
||||||
|
Code: http.StatusBadRequest,
|
||||||
|
}
|
||||||
|
network.WriteError(w, errJson)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
bs.proposeBlock(r.Context(), w, genericBlock)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
altairBlock := ðpbv2.SignedBeaconBlockAltair{}
|
||||||
|
if err := altairBlock.UnmarshalSSZ(body); err == nil {
|
||||||
|
if err = validate.Struct(altairBlock); err == nil {
|
||||||
|
v1block, err := migration.AltairToV1Alpha1SignedBlock(altairBlock)
|
||||||
|
if err != nil {
|
||||||
|
errJson := &network.DefaultErrorJson{
|
||||||
|
Message: "Could not decode request body into consensus block: " + err.Error(),
|
||||||
|
Code: http.StatusBadRequest,
|
||||||
|
}
|
||||||
|
network.WriteError(w, errJson)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
genericBlock := ð.GenericSignedBeaconBlock{
|
||||||
|
Block: ð.GenericSignedBeaconBlock_Altair{
|
||||||
|
Altair: v1block,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if err = bs.validateBroadcast(r, genericBlock); err != nil {
|
||||||
|
errJson := &network.DefaultErrorJson{
|
||||||
|
Message: err.Error(),
|
||||||
|
Code: http.StatusBadRequest,
|
||||||
|
}
|
||||||
|
network.WriteError(w, errJson)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
bs.proposeBlock(r.Context(), w, genericBlock)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
phase0Block := ðpbv1.SignedBeaconBlock{}
|
||||||
|
if err := phase0Block.UnmarshalSSZ(body); err == nil {
|
||||||
|
if err = validate.Struct(phase0Block); err == nil {
|
||||||
|
v1block, err := migration.V1ToV1Alpha1SignedBlock(phase0Block)
|
||||||
|
if err != nil {
|
||||||
|
errJson := &network.DefaultErrorJson{
|
||||||
|
Message: "Could not decode request body into consensus block: " + err.Error(),
|
||||||
|
Code: http.StatusBadRequest,
|
||||||
|
}
|
||||||
|
network.WriteError(w, errJson)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
genericBlock := ð.GenericSignedBeaconBlock{
|
||||||
|
Block: ð.GenericSignedBeaconBlock_Phase0{
|
||||||
|
Phase0: v1block,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if err = bs.validateBroadcast(r, genericBlock); err != nil {
|
||||||
|
errJson := &network.DefaultErrorJson{
|
||||||
|
Message: err.Error(),
|
||||||
|
Code: http.StatusBadRequest,
|
||||||
|
}
|
||||||
|
network.WriteError(w, errJson)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
bs.proposeBlock(r.Context(), w, genericBlock)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
errJson := &network.DefaultErrorJson{
|
||||||
|
Message: "Body does not represent a valid block type",
|
||||||
|
Code: http.StatusBadRequest,
|
||||||
|
}
|
||||||
|
network.WriteError(w, errJson)
|
||||||
|
}
|
||||||
|
|
||||||
|
func publishBlockV2(bs *Server, w http.ResponseWriter, r *http.Request) {
|
||||||
|
validate := validator.New()
|
||||||
|
body, err := io.ReadAll(r.Body)
|
||||||
|
if err != nil {
|
||||||
|
errJson := &network.DefaultErrorJson{
|
||||||
|
Message: "Could not read request body",
|
||||||
|
Code: http.StatusInternalServerError,
|
||||||
|
}
|
||||||
|
network.WriteError(w, errJson)
|
||||||
|
return
|
||||||
|
}
|
||||||
var capellaBlock *SignedBeaconBlockCapella
|
var capellaBlock *SignedBeaconBlockCapella
|
||||||
if err = unmarshalStrict(body, &capellaBlock); err == nil {
|
if err = unmarshalStrict(body, &capellaBlock); err == nil {
|
||||||
if err = validate.Struct(capellaBlock); err == nil {
|
if err = validate.Struct(capellaBlock); err == nil {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package beacon
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -13,6 +14,7 @@ import (
|
|||||||
eth "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
|
eth "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
|
||||||
"github.com/prysmaticlabs/prysm/v4/testing/assert"
|
"github.com/prysmaticlabs/prysm/v4/testing/assert"
|
||||||
mock2 "github.com/prysmaticlabs/prysm/v4/testing/mock"
|
mock2 "github.com/prysmaticlabs/prysm/v4/testing/mock"
|
||||||
|
"github.com/prysmaticlabs/prysm/v4/testing/require"
|
||||||
"github.com/stretchr/testify/mock"
|
"github.com/stretchr/testify/mock"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -30,7 +32,7 @@ func TestPublishBlockV2(t *testing.T) {
|
|||||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||||
}
|
}
|
||||||
|
|
||||||
request := httptest.NewRequest("GET", "http://foo.example", bytes.NewReader([]byte(phase0Block)))
|
request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(phase0Block)))
|
||||||
writer := httptest.NewRecorder()
|
writer := httptest.NewRecorder()
|
||||||
writer.Body = &bytes.Buffer{}
|
writer.Body = &bytes.Buffer{}
|
||||||
server.PublishBlockV2(writer, request)
|
server.PublishBlockV2(writer, request)
|
||||||
@@ -47,7 +49,7 @@ func TestPublishBlockV2(t *testing.T) {
|
|||||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||||
}
|
}
|
||||||
|
|
||||||
request := httptest.NewRequest("GET", "http://foo.example", bytes.NewReader([]byte(altairBlock)))
|
request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(altairBlock)))
|
||||||
writer := httptest.NewRecorder()
|
writer := httptest.NewRecorder()
|
||||||
writer.Body = &bytes.Buffer{}
|
writer.Body = &bytes.Buffer{}
|
||||||
server.PublishBlockV2(writer, request)
|
server.PublishBlockV2(writer, request)
|
||||||
@@ -64,7 +66,7 @@ func TestPublishBlockV2(t *testing.T) {
|
|||||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||||
}
|
}
|
||||||
|
|
||||||
request := httptest.NewRequest("GET", "http://foo.example", bytes.NewReader([]byte(bellatrixBlock)))
|
request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(bellatrixBlock)))
|
||||||
writer := httptest.NewRecorder()
|
writer := httptest.NewRecorder()
|
||||||
writer.Body = &bytes.Buffer{}
|
writer.Body = &bytes.Buffer{}
|
||||||
server.PublishBlockV2(writer, request)
|
server.PublishBlockV2(writer, request)
|
||||||
@@ -81,7 +83,7 @@ func TestPublishBlockV2(t *testing.T) {
|
|||||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||||
}
|
}
|
||||||
|
|
||||||
request := httptest.NewRequest("GET", "http://foo.example", bytes.NewReader([]byte(capellaBlock)))
|
request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(capellaBlock)))
|
||||||
writer := httptest.NewRecorder()
|
writer := httptest.NewRecorder()
|
||||||
writer.Body = &bytes.Buffer{}
|
writer.Body = &bytes.Buffer{}
|
||||||
server.PublishBlockV2(writer, request)
|
server.PublishBlockV2(writer, request)
|
||||||
@@ -92,7 +94,7 @@ func TestPublishBlockV2(t *testing.T) {
|
|||||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||||
}
|
}
|
||||||
|
|
||||||
request := httptest.NewRequest("GET", "http://foo.example", bytes.NewReader([]byte(blindedBellatrixBlock)))
|
request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(blindedBellatrixBlock)))
|
||||||
writer := httptest.NewRecorder()
|
writer := httptest.NewRecorder()
|
||||||
writer.Body = &bytes.Buffer{}
|
writer.Body = &bytes.Buffer{}
|
||||||
server.PublishBlockV2(writer, request)
|
server.PublishBlockV2(writer, request)
|
||||||
@@ -108,7 +110,7 @@ func TestPublishBlockV2(t *testing.T) {
|
|||||||
OptimisticModeFetcher: chainService,
|
OptimisticModeFetcher: chainService,
|
||||||
}
|
}
|
||||||
|
|
||||||
request := httptest.NewRequest("GET", "http://foo.example", bytes.NewReader([]byte("foo")))
|
request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte("foo")))
|
||||||
writer := httptest.NewRecorder()
|
writer := httptest.NewRecorder()
|
||||||
writer.Body = &bytes.Buffer{}
|
writer.Body = &bytes.Buffer{}
|
||||||
server.PublishBlockV2(writer, request)
|
server.PublishBlockV2(writer, request)
|
||||||
@@ -117,9 +119,74 @@ func TestPublishBlockV2(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPublishBlindedBlockV2(t *testing.T) {
|
func TestPublishBlockV2SSZ(t *testing.T) {
|
||||||
ctrl := gomock.NewController(t)
|
ctrl := gomock.NewController(t)
|
||||||
|
|
||||||
|
t.Run("Bellatrix", func(t *testing.T) {
|
||||||
|
v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl)
|
||||||
|
v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool {
|
||||||
|
_, ok := req.Block.(*eth.GenericSignedBeaconBlock_Bellatrix)
|
||||||
|
return ok
|
||||||
|
}))
|
||||||
|
server := &Server{
|
||||||
|
V1Alpha1ValidatorServer: v1alpha1Server,
|
||||||
|
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||||
|
}
|
||||||
|
var bellablock SignedBeaconBlockBellatrix
|
||||||
|
err := json.Unmarshal([]byte(bellatrixBlock), &bellablock)
|
||||||
|
require.NoError(t, err)
|
||||||
|
genericBlock, err := bellablock.ToGeneric()
|
||||||
|
require.NoError(t, err)
|
||||||
|
sszvalue, err := genericBlock.GetBellatrix().MarshalSSZ()
|
||||||
|
require.NoError(t, err)
|
||||||
|
request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader(sszvalue))
|
||||||
|
request.Header.Set("Accept", "application/octet-stream")
|
||||||
|
writer := httptest.NewRecorder()
|
||||||
|
writer.Body = &bytes.Buffer{}
|
||||||
|
server.PublishBlockV2(writer, request)
|
||||||
|
assert.Equal(t, http.StatusOK, writer.Code)
|
||||||
|
})
|
||||||
|
t.Run("Capella", func(t *testing.T) {
|
||||||
|
v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl)
|
||||||
|
v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool {
|
||||||
|
_, ok := req.Block.(*eth.GenericSignedBeaconBlock_Capella)
|
||||||
|
return ok
|
||||||
|
}))
|
||||||
|
server := &Server{
|
||||||
|
V1Alpha1ValidatorServer: v1alpha1Server,
|
||||||
|
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||||
|
}
|
||||||
|
|
||||||
|
var cblock SignedBeaconBlockCapella
|
||||||
|
err := json.Unmarshal([]byte(capellaBlock), &cblock)
|
||||||
|
require.NoError(t, err)
|
||||||
|
genericBlock, err := cblock.ToGeneric()
|
||||||
|
require.NoError(t, err)
|
||||||
|
sszvalue, err := genericBlock.GetCapella().MarshalSSZ()
|
||||||
|
require.NoError(t, err)
|
||||||
|
request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader(sszvalue))
|
||||||
|
request.Header.Set("Accept", "application/octet-stream")
|
||||||
|
writer := httptest.NewRecorder()
|
||||||
|
writer.Body = &bytes.Buffer{}
|
||||||
|
server.PublishBlockV2(writer, request)
|
||||||
|
assert.Equal(t, http.StatusOK, writer.Code)
|
||||||
|
})
|
||||||
|
t.Run("invalid block", func(t *testing.T) {
|
||||||
|
server := &Server{
|
||||||
|
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||||
|
}
|
||||||
|
|
||||||
|
request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(blindedBellatrixBlock)))
|
||||||
|
writer := httptest.NewRecorder()
|
||||||
|
writer.Body = &bytes.Buffer{}
|
||||||
|
server.PublishBlockV2(writer, request)
|
||||||
|
assert.Equal(t, http.StatusBadRequest, writer.Code)
|
||||||
|
assert.Equal(t, true, strings.Contains(writer.Body.String(), "Body does not represent a valid block type"))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPublishBlindedBlockV2(t *testing.T) {
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
t.Run("Phase 0", func(t *testing.T) {
|
t.Run("Phase 0", func(t *testing.T) {
|
||||||
v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl)
|
v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl)
|
||||||
v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool {
|
v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool {
|
||||||
@@ -131,7 +198,7 @@ func TestPublishBlindedBlockV2(t *testing.T) {
|
|||||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||||
}
|
}
|
||||||
|
|
||||||
request := httptest.NewRequest("GET", "http://foo.example", bytes.NewReader([]byte(phase0Block)))
|
request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(phase0Block)))
|
||||||
writer := httptest.NewRecorder()
|
writer := httptest.NewRecorder()
|
||||||
writer.Body = &bytes.Buffer{}
|
writer.Body = &bytes.Buffer{}
|
||||||
server.PublishBlindedBlockV2(writer, request)
|
server.PublishBlindedBlockV2(writer, request)
|
||||||
@@ -148,7 +215,7 @@ func TestPublishBlindedBlockV2(t *testing.T) {
|
|||||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||||
}
|
}
|
||||||
|
|
||||||
request := httptest.NewRequest("GET", "http://foo.example", bytes.NewReader([]byte(altairBlock)))
|
request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(altairBlock)))
|
||||||
writer := httptest.NewRecorder()
|
writer := httptest.NewRecorder()
|
||||||
writer.Body = &bytes.Buffer{}
|
writer.Body = &bytes.Buffer{}
|
||||||
server.PublishBlindedBlockV2(writer, request)
|
server.PublishBlindedBlockV2(writer, request)
|
||||||
@@ -165,7 +232,7 @@ func TestPublishBlindedBlockV2(t *testing.T) {
|
|||||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||||
}
|
}
|
||||||
|
|
||||||
request := httptest.NewRequest("GET", "http://foo.example", bytes.NewReader([]byte(blindedBellatrixBlock)))
|
request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(blindedBellatrixBlock)))
|
||||||
writer := httptest.NewRecorder()
|
writer := httptest.NewRecorder()
|
||||||
writer.Body = &bytes.Buffer{}
|
writer.Body = &bytes.Buffer{}
|
||||||
server.PublishBlindedBlockV2(writer, request)
|
server.PublishBlindedBlockV2(writer, request)
|
||||||
@@ -182,7 +249,7 @@ func TestPublishBlindedBlockV2(t *testing.T) {
|
|||||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||||
}
|
}
|
||||||
|
|
||||||
request := httptest.NewRequest("GET", "http://foo.example", bytes.NewReader([]byte(blindedCapellaBlock)))
|
request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(blindedCapellaBlock)))
|
||||||
writer := httptest.NewRecorder()
|
writer := httptest.NewRecorder()
|
||||||
writer.Body = &bytes.Buffer{}
|
writer.Body = &bytes.Buffer{}
|
||||||
server.PublishBlindedBlockV2(writer, request)
|
server.PublishBlindedBlockV2(writer, request)
|
||||||
@@ -193,7 +260,7 @@ func TestPublishBlindedBlockV2(t *testing.T) {
|
|||||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||||
}
|
}
|
||||||
|
|
||||||
request := httptest.NewRequest("GET", "http://foo.example", bytes.NewReader([]byte(bellatrixBlock)))
|
request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(bellatrixBlock)))
|
||||||
writer := httptest.NewRecorder()
|
writer := httptest.NewRecorder()
|
||||||
writer.Body = &bytes.Buffer{}
|
writer.Body = &bytes.Buffer{}
|
||||||
server.PublishBlindedBlockV2(writer, request)
|
server.PublishBlindedBlockV2(writer, request)
|
||||||
@@ -209,7 +276,7 @@ func TestPublishBlindedBlockV2(t *testing.T) {
|
|||||||
OptimisticModeFetcher: chainService,
|
OptimisticModeFetcher: chainService,
|
||||||
}
|
}
|
||||||
|
|
||||||
request := httptest.NewRequest("GET", "http://foo.example", bytes.NewReader([]byte("foo")))
|
request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte("foo")))
|
||||||
writer := httptest.NewRecorder()
|
writer := httptest.NewRecorder()
|
||||||
writer.Body = &bytes.Buffer{}
|
writer.Body = &bytes.Buffer{}
|
||||||
server.PublishBlindedBlockV2(writer, request)
|
server.PublishBlindedBlockV2(writer, request)
|
||||||
@@ -218,6 +285,72 @@ func TestPublishBlindedBlockV2(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPublishBlindedBlockV2SSZ(t *testing.T) {
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
t.Run("Bellatrix", func(t *testing.T) {
|
||||||
|
v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl)
|
||||||
|
v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool {
|
||||||
|
_, ok := req.Block.(*eth.GenericSignedBeaconBlock_BlindedBellatrix)
|
||||||
|
return ok
|
||||||
|
}))
|
||||||
|
server := &Server{
|
||||||
|
V1Alpha1ValidatorServer: v1alpha1Server,
|
||||||
|
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||||
|
}
|
||||||
|
|
||||||
|
var bellablock SignedBlindedBeaconBlockBellatrix
|
||||||
|
err := json.Unmarshal([]byte(blindedBellatrixBlock), &bellablock)
|
||||||
|
require.NoError(t, err)
|
||||||
|
genericBlock, err := bellablock.ToGeneric()
|
||||||
|
require.NoError(t, err)
|
||||||
|
sszvalue, err := genericBlock.GetBlindedBellatrix().MarshalSSZ()
|
||||||
|
require.NoError(t, err)
|
||||||
|
request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader(sszvalue))
|
||||||
|
request.Header.Set("Accept", "application/octet-stream")
|
||||||
|
writer := httptest.NewRecorder()
|
||||||
|
writer.Body = &bytes.Buffer{}
|
||||||
|
server.PublishBlindedBlockV2(writer, request)
|
||||||
|
assert.Equal(t, http.StatusOK, writer.Code)
|
||||||
|
})
|
||||||
|
t.Run("Capella", func(t *testing.T) {
|
||||||
|
v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl)
|
||||||
|
v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool {
|
||||||
|
_, ok := req.Block.(*eth.GenericSignedBeaconBlock_BlindedCapella)
|
||||||
|
return ok
|
||||||
|
}))
|
||||||
|
server := &Server{
|
||||||
|
V1Alpha1ValidatorServer: v1alpha1Server,
|
||||||
|
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||||
|
}
|
||||||
|
|
||||||
|
var cblock SignedBlindedBeaconBlockCapella
|
||||||
|
err := json.Unmarshal([]byte(blindedCapellaBlock), &cblock)
|
||||||
|
require.NoError(t, err)
|
||||||
|
genericBlock, err := cblock.ToGeneric()
|
||||||
|
require.NoError(t, err)
|
||||||
|
sszvalue, err := genericBlock.GetBlindedCapella().MarshalSSZ()
|
||||||
|
require.NoError(t, err)
|
||||||
|
request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader(sszvalue))
|
||||||
|
request.Header.Set("Accept", "application/octet-stream")
|
||||||
|
writer := httptest.NewRecorder()
|
||||||
|
writer.Body = &bytes.Buffer{}
|
||||||
|
server.PublishBlindedBlockV2(writer, request)
|
||||||
|
assert.Equal(t, http.StatusOK, writer.Code)
|
||||||
|
})
|
||||||
|
t.Run("invalid block", func(t *testing.T) {
|
||||||
|
server := &Server{
|
||||||
|
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||||
|
}
|
||||||
|
|
||||||
|
request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(bellatrixBlock)))
|
||||||
|
writer := httptest.NewRecorder()
|
||||||
|
writer.Body = &bytes.Buffer{}
|
||||||
|
server.PublishBlindedBlockV2(writer, request)
|
||||||
|
assert.Equal(t, http.StatusBadRequest, writer.Code)
|
||||||
|
assert.Equal(t, true, strings.Contains(writer.Body.String(), "Body does not represent a valid block type"))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
phase0Block = `{
|
phase0Block = `{
|
||||||
"message": {
|
"message": {
|
||||||
@@ -668,7 +801,8 @@ const (
|
|||||||
"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
|
"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
|
||||||
"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
|
"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
|
||||||
"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
|
"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
|
||||||
"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
|
"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
|
||||||
|
"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
|
||||||
],
|
],
|
||||||
"data": {
|
"data": {
|
||||||
"pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a",
|
"pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a",
|
||||||
@@ -688,7 +822,7 @@ const (
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"sync_aggregate": {
|
"sync_aggregate": {
|
||||||
"sync_committee_bits": "0x01",
|
"sync_committee_bits": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
"sync_committee_signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505"
|
"sync_committee_signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505"
|
||||||
},
|
},
|
||||||
"execution_payload": {
|
"execution_payload": {
|
||||||
@@ -846,7 +980,8 @@ const (
|
|||||||
"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
|
"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
|
||||||
"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
|
"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
|
||||||
"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
|
"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
|
||||||
"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
|
"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
|
||||||
|
"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
|
||||||
],
|
],
|
||||||
"data": {
|
"data": {
|
||||||
"pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a",
|
"pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a",
|
||||||
@@ -866,7 +1001,7 @@ const (
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"sync_aggregate": {
|
"sync_aggregate": {
|
||||||
"sync_committee_bits": "0x01",
|
"sync_committee_bits": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
"sync_committee_signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505"
|
"sync_committee_signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505"
|
||||||
},
|
},
|
||||||
"execution_payload_header": {
|
"execution_payload_header": {
|
||||||
@@ -1022,7 +1157,8 @@ const (
|
|||||||
"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
|
"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
|
||||||
"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
|
"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
|
||||||
"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
|
"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
|
||||||
"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
|
"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
|
||||||
|
"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
|
||||||
],
|
],
|
||||||
"data": {
|
"data": {
|
||||||
"pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a",
|
"pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a",
|
||||||
@@ -1042,7 +1178,7 @@ const (
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"sync_aggregate": {
|
"sync_aggregate": {
|
||||||
"sync_committee_bits": "0x01",
|
"sync_committee_bits": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
"sync_committee_signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505"
|
"sync_committee_signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505"
|
||||||
},
|
},
|
||||||
"execution_payload": {
|
"execution_payload": {
|
||||||
@@ -1218,7 +1354,8 @@ const (
|
|||||||
"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
|
"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
|
||||||
"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
|
"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
|
||||||
"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
|
"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
|
||||||
"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
|
"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
|
||||||
|
"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
|
||||||
],
|
],
|
||||||
"data": {
|
"data": {
|
||||||
"pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a",
|
"pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a",
|
||||||
@@ -1238,7 +1375,7 @@ const (
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"sync_aggregate": {
|
"sync_aggregate": {
|
||||||
"sync_committee_bits": "0x01",
|
"sync_committee_bits": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
"sync_committee_signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505"
|
"sync_committee_signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505"
|
||||||
},
|
},
|
||||||
"execution_payload_header": {
|
"execution_payload_header": {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"net/http"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
@@ -218,16 +219,17 @@ func (s *Service) Start() {
|
|||||||
Stater: stater,
|
Stater: stater,
|
||||||
HeadFetcher: s.cfg.HeadFetcher,
|
HeadFetcher: s.cfg.HeadFetcher,
|
||||||
}
|
}
|
||||||
s.cfg.Router.HandleFunc("/eth/v1/beacon/rewards/blocks/{block_id}", rewardsServer.BlockRewards)
|
|
||||||
s.cfg.Router.HandleFunc("/eth/v1/beacon/rewards/attestations/{epoch}", rewardsServer.AttestationRewards)
|
s.cfg.Router.HandleFunc("/eth/v1/beacon/rewards/blocks/{block_id}", rewardsServer.BlockRewards).Methods(http.MethodGet)
|
||||||
s.cfg.Router.HandleFunc("/eth/v1/beacon/rewards/sync_committee/{block_id}", rewardsServer.SyncCommitteeRewards)
|
s.cfg.Router.HandleFunc("/eth/v1/beacon/rewards/attestations/{epoch}", rewardsServer.AttestationRewards).Methods(http.MethodPost)
|
||||||
|
s.cfg.Router.HandleFunc("/eth/v1/beacon/rewards/sync_committee/{block_id}", rewardsServer.SyncCommitteeRewards).Methods(http.MethodPost)
|
||||||
|
|
||||||
builderServer := &rpcBuilder.Server{
|
builderServer := &rpcBuilder.Server{
|
||||||
FinalizationFetcher: s.cfg.FinalizationFetcher,
|
FinalizationFetcher: s.cfg.FinalizationFetcher,
|
||||||
OptimisticModeFetcher: s.cfg.OptimisticModeFetcher,
|
OptimisticModeFetcher: s.cfg.OptimisticModeFetcher,
|
||||||
Stater: stater,
|
Stater: stater,
|
||||||
}
|
}
|
||||||
s.cfg.Router.HandleFunc("/eth/v1/builder/states/{state_id}/expected_withdrawals", builderServer.ExpectedWithdrawals)
|
s.cfg.Router.HandleFunc("/eth/v1/builder/states/{state_id}/expected_withdrawals", builderServer.ExpectedWithdrawals).Methods(http.MethodGet)
|
||||||
|
|
||||||
validatorServer := &validatorv1alpha1.Server{
|
validatorServer := &validatorv1alpha1.Server{
|
||||||
Ctx: s.ctx,
|
Ctx: s.ctx,
|
||||||
@@ -321,9 +323,9 @@ func (s *Service) Start() {
|
|||||||
ExecutionChainInfoFetcher: s.cfg.ExecutionChainInfoFetcher,
|
ExecutionChainInfoFetcher: s.cfg.ExecutionChainInfoFetcher,
|
||||||
}
|
}
|
||||||
|
|
||||||
s.cfg.Router.HandleFunc("/prysm/node/trusted_peers", nodeServerPrysm.ListTrustedPeer).Methods("GET")
|
s.cfg.Router.HandleFunc("/prysm/node/trusted_peers", nodeServerPrysm.ListTrustedPeer).Methods(http.MethodGet)
|
||||||
s.cfg.Router.HandleFunc("/prysm/node/trusted_peers", nodeServerPrysm.AddTrustedPeer).Methods("POST")
|
s.cfg.Router.HandleFunc("/prysm/node/trusted_peers", nodeServerPrysm.AddTrustedPeer).Methods(http.MethodPost)
|
||||||
s.cfg.Router.HandleFunc("/prysm/node/trusted_peers/{peer_id}", nodeServerPrysm.RemoveTrustedPeer).Methods("Delete")
|
s.cfg.Router.HandleFunc("/prysm/node/trusted_peers/{peer_id}", nodeServerPrysm.RemoveTrustedPeer).Methods(http.MethodDelete)
|
||||||
|
|
||||||
beaconChainServer := &beaconv1alpha1.Server{
|
beaconChainServer := &beaconv1alpha1.Server{
|
||||||
Ctx: s.ctx,
|
Ctx: s.ctx,
|
||||||
@@ -378,9 +380,9 @@ func (s *Service) Start() {
|
|||||||
HeadFetcher: s.cfg.HeadFetcher,
|
HeadFetcher: s.cfg.HeadFetcher,
|
||||||
SyncChecker: s.cfg.SyncService,
|
SyncChecker: s.cfg.SyncService,
|
||||||
}
|
}
|
||||||
s.cfg.Router.HandleFunc("/prysm/validators/performance", httpServer.GetValidatorPerformance)
|
s.cfg.Router.HandleFunc("/prysm/validators/performance", httpServer.GetValidatorPerformance).Methods(http.MethodGet)
|
||||||
s.cfg.Router.HandleFunc("/eth/v2/beacon/blocks", beaconChainServerV1.PublishBlockV2)
|
s.cfg.Router.HandleFunc("/eth/v2/beacon/blocks", beaconChainServerV1.PublishBlockV2).Methods(http.MethodPost)
|
||||||
s.cfg.Router.HandleFunc("/eth/v2/beacon/blinded_blocks", beaconChainServerV1.PublishBlindedBlockV2)
|
s.cfg.Router.HandleFunc("/eth/v2/beacon/blinded_blocks", beaconChainServerV1.PublishBlindedBlockV2).Methods(http.MethodPost)
|
||||||
ethpbv1alpha1.RegisterNodeServer(s.grpcServer, nodeServer)
|
ethpbv1alpha1.RegisterNodeServer(s.grpcServer, nodeServer)
|
||||||
ethpbservice.RegisterBeaconNodeServer(s.grpcServer, nodeServerV1)
|
ethpbservice.RegisterBeaconNodeServer(s.grpcServer, nodeServerV1)
|
||||||
ethpbv1alpha1.RegisterHealthServer(s.grpcServer, nodeServer)
|
ethpbv1alpha1.RegisterHealthServer(s.grpcServer, nodeServer)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ go_library(
|
|||||||
"auth.go",
|
"auth.go",
|
||||||
"endpoint.go",
|
"endpoint.go",
|
||||||
"external_ip.go",
|
"external_ip.go",
|
||||||
|
"reader.go",
|
||||||
"writer.go",
|
"writer.go",
|
||||||
],
|
],
|
||||||
importpath = "github.com/prysmaticlabs/prysm/v4/network",
|
importpath = "github.com/prysmaticlabs/prysm/v4/network",
|
||||||
@@ -25,6 +26,7 @@ go_test(
|
|||||||
"auth_test.go",
|
"auth_test.go",
|
||||||
"endpoint_test.go",
|
"endpoint_test.go",
|
||||||
"external_ip_test.go",
|
"external_ip_test.go",
|
||||||
|
"reader_test.go",
|
||||||
],
|
],
|
||||||
embed = [":go_default_library"],
|
embed = [":go_default_library"],
|
||||||
deps = [
|
deps = [
|
||||||
|
|||||||
51
network/reader.go
Normal file
51
network/reader.go
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
package network
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// match a number with optional decimals
|
||||||
|
var priorityRegex = regexp.MustCompile(`q=(\d+(?:\.\d+)?)`)
|
||||||
|
|
||||||
|
// SszRequested takes a http request and checks to see if it should be requesting a ssz response.
|
||||||
|
func SszRequested(req *http.Request) (bool, error) {
|
||||||
|
accept := req.Header.Values("Accept")
|
||||||
|
if len(accept) == 0 {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
types := strings.Split(accept[0], ",")
|
||||||
|
currentType, currentPriority := "", 0.0
|
||||||
|
for _, t := range types {
|
||||||
|
values := strings.Split(t, ";")
|
||||||
|
name := values[0]
|
||||||
|
if name != jsonMediaType && name != octetStreamMediaType {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// no params specified
|
||||||
|
if len(values) == 1 {
|
||||||
|
priority := 1.0
|
||||||
|
if priority > currentPriority {
|
||||||
|
currentType, currentPriority = name, priority
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
params := values[1]
|
||||||
|
|
||||||
|
match := priorityRegex.FindAllStringSubmatch(params, 1)
|
||||||
|
if len(match) != 1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
priority, err := strconv.ParseFloat(match[0][1], 32)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if priority > currentPriority {
|
||||||
|
currentType, currentPriority = name, priority
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return currentType == octetStreamMediaType, nil
|
||||||
|
}
|
||||||
99
network/reader_test.go
Normal file
99
network/reader_test.go
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
package network
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/prysmaticlabs/prysm/v4/testing/assert"
|
||||||
|
"github.com/prysmaticlabs/prysm/v4/testing/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSSZRequested(t *testing.T) {
|
||||||
|
t.Run("ssz_requested", func(t *testing.T) {
|
||||||
|
request := httptest.NewRequest("GET", "http://foo.example", nil)
|
||||||
|
request.Header["Accept"] = []string{octetStreamMediaType}
|
||||||
|
result, err := SszRequested(request)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, true, result)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("ssz_content_type_first", func(t *testing.T) {
|
||||||
|
request := httptest.NewRequest("GET", "http://foo.example", nil)
|
||||||
|
request.Header["Accept"] = []string{fmt.Sprintf("%s,%s", octetStreamMediaType, jsonMediaType)}
|
||||||
|
result, err := SszRequested(request)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, true, result)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("ssz_content_type_preferred_1", func(t *testing.T) {
|
||||||
|
request := httptest.NewRequest("GET", "http://foo.example", nil)
|
||||||
|
request.Header["Accept"] = []string{fmt.Sprintf("%s;q=0.9,%s", jsonMediaType, octetStreamMediaType)}
|
||||||
|
result, err := SszRequested(request)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, true, result)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("ssz_content_type_preferred_2", func(t *testing.T) {
|
||||||
|
request := httptest.NewRequest("GET", "http://foo.example", nil)
|
||||||
|
request.Header["Accept"] = []string{fmt.Sprintf("%s;q=0.95,%s;q=0.9", octetStreamMediaType, jsonMediaType)}
|
||||||
|
result, err := SszRequested(request)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, true, result)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("other_content_type_preferred", func(t *testing.T) {
|
||||||
|
request := httptest.NewRequest("GET", "http://foo.example", nil)
|
||||||
|
request.Header["Accept"] = []string{fmt.Sprintf("%s,%s;q=0.9", jsonMediaType, octetStreamMediaType)}
|
||||||
|
result, err := SszRequested(request)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, false, result)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("other_params", func(t *testing.T) {
|
||||||
|
request := httptest.NewRequest("GET", "http://foo.example", nil)
|
||||||
|
request.Header["Accept"] = []string{fmt.Sprintf("%s,%s;q=0.9,otherparam=xyz", jsonMediaType, octetStreamMediaType)}
|
||||||
|
result, err := SszRequested(request)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, false, result)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("no_header", func(t *testing.T) {
|
||||||
|
request := httptest.NewRequest("GET", "http://foo.example", nil)
|
||||||
|
result, err := SszRequested(request)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, false, result)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("empty_header", func(t *testing.T) {
|
||||||
|
request := httptest.NewRequest("GET", "http://foo.example", nil)
|
||||||
|
request.Header["Accept"] = []string{}
|
||||||
|
result, err := SszRequested(request)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, false, result)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("empty_header_value", func(t *testing.T) {
|
||||||
|
request := httptest.NewRequest("GET", "http://foo.example", nil)
|
||||||
|
request.Header["Accept"] = []string{""}
|
||||||
|
result, err := SszRequested(request)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, false, result)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("other_content_type", func(t *testing.T) {
|
||||||
|
request := httptest.NewRequest("GET", "http://foo.example", nil)
|
||||||
|
request.Header["Accept"] = []string{"application/other"}
|
||||||
|
result, err := SszRequested(request)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, false, result)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("garbage", func(t *testing.T) {
|
||||||
|
request := httptest.NewRequest("GET", "http://foo.example", nil)
|
||||||
|
request.Header["Accept"] = []string{"This is Sparta!!!"}
|
||||||
|
result, err := SszRequested(request)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, false, result)
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -10,6 +10,11 @@ import (
|
|||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
jsonMediaType = "application/json"
|
||||||
|
octetStreamMediaType = "application/octet-stream"
|
||||||
|
)
|
||||||
|
|
||||||
// DefaultErrorJson is a JSON representation of a simple error value, containing only a message and an error code.
|
// DefaultErrorJson is a JSON representation of a simple error value, containing only a message and an error code.
|
||||||
type DefaultErrorJson struct {
|
type DefaultErrorJson struct {
|
||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
@@ -18,13 +23,23 @@ type DefaultErrorJson struct {
|
|||||||
|
|
||||||
// WriteJson writes the response message in JSON format.
|
// WriteJson writes the response message in JSON format.
|
||||||
func WriteJson(w http.ResponseWriter, v any) {
|
func WriteJson(w http.ResponseWriter, v any) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", jsonMediaType)
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
if err := json.NewEncoder(w).Encode(v); err != nil {
|
if err := json.NewEncoder(w).Encode(v); err != nil {
|
||||||
log.WithError(err).Error("Could not write response message")
|
log.WithError(err).Error("Could not write response message")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WriteSsz writes the response message in ssz format
|
||||||
|
func WriteSsz(w http.ResponseWriter, respSsz []byte, fileName string) {
|
||||||
|
w.Header().Set("Content-Length", strconv.Itoa(len(respSsz)))
|
||||||
|
w.Header().Set("Content-Type", octetStreamMediaType)
|
||||||
|
w.Header().Set("Content-Disposition", "attachment; filename="+fileName)
|
||||||
|
if _, err := io.Copy(w, io.NopCloser(bytes.NewReader(respSsz))); err != nil {
|
||||||
|
log.WithError(err).Error("could not write response message")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// WriteError writes the error by manipulating headers and the body of the final response.
|
// WriteError writes the error by manipulating headers and the body of the final response.
|
||||||
func WriteError(w http.ResponseWriter, errJson *DefaultErrorJson) {
|
func WriteError(w http.ResponseWriter, errJson *DefaultErrorJson) {
|
||||||
j, err := json.Marshal(errJson)
|
j, err := json.Marshal(errJson)
|
||||||
|
|||||||
Reference in New Issue
Block a user