From c312a88aa391ee3c62877c637ca88b77981f19b2 Mon Sep 17 00:00:00 2001 From: kasey <489222+kasey@users.noreply.github.com> Date: Thu, 2 May 2024 15:52:27 -0500 Subject: [PATCH] Removes fork-specific concrete type getters (#13941) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * removing typed pb accessors * refactor ssz api resp handlers to avoid typed pbs * json get block handler refactor * SubmitBlindedBlock to use generic json handling * update SubmitBlindedBlock * clear out more usages of PbForkname methods * remove fork-specific getters from block interface * remove usages of payload pb methods * remove pb helpers from execution payload interface * Update beacon-chain/rpc/eth/beacon/handlers.go Co-authored-by: Radosław Kapka * Update beacon-chain/rpc/eth/beacon/handlers.go Co-authored-by: Radosław Kapka * Update api/client/builder/client.go Co-authored-by: Radosław Kapka * Update api/client/builder/client.go Co-authored-by: Radosław Kapka * Update api/client/builder/client.go Co-authored-by: Radosław Kapka * Update api/client/builder/client.go Co-authored-by: Radosław Kapka * Update api/client/builder/client.go Co-authored-by: Radosław Kapka * Radek review * fix error message * deal with wonky builder responses * :scissors: * gaz * lint * tweaks for deep source --------- Co-authored-by: Kasey Kirkham Co-authored-by: Radosław Kapka --- api/client/builder/BUILD.bazel | 3 + api/client/builder/client.go | 170 ++-- api/client/builder/client_test.go | 2 +- api/client/builder/types.go | 125 +++ api/client/builder/types_test.go | 40 +- api/server/structs/BUILD.bazel | 1 + api/server/structs/block.go | 94 +++ api/server/structs/conversions_block.go | 33 +- beacon-chain/db/kv/BUILD.bazel | 1 + beacon-chain/db/kv/blocks_test.go | 103 +-- beacon-chain/execution/engine_client_test.go | 36 +- beacon-chain/rpc/eth/beacon/BUILD.bazel | 1 + beacon-chain/rpc/eth/beacon/handlers.go | 790 ++---------------- beacon-chain/rpc/lookup/blocker_test.go | 4 +- .../rpc/prysm/v1alpha1/beacon/blocks.go | 79 +- .../rpc/prysm/v1alpha1/beacon/blocks_test.go | 9 +- .../v1alpha1/validator/proposer_deneb.go | 6 +- consensus-types/blocks/execution.go | 137 +-- consensus-types/blocks/execution_test.go | 38 - consensus-types/blocks/getters.go | 96 --- consensus-types/blocks/testing/BUILD.bazel | 1 - consensus-types/blocks/testing/mutator.go | 44 +- consensus-types/interfaces/beacon_block.go | 12 - consensus-types/mock/block.go | 32 - testing/middleware/builder/builder.go | 75 +- validator/client/propose.go | 7 +- 26 files changed, 525 insertions(+), 1414 deletions(-) diff --git a/api/client/builder/BUILD.bazel b/api/client/builder/BUILD.bazel index 5f5335a161cf..6248a2051e75 100644 --- a/api/client/builder/BUILD.bazel +++ b/api/client/builder/BUILD.bazel @@ -11,6 +11,7 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/v5/api/client/builder", visibility = ["//visibility:public"], deps = [ + "//api:go_default_library", "//api/server/structs:go_default_library", "//config/fieldparams:go_default_library", "//consensus-types:go_default_library", @@ -28,6 +29,7 @@ go_library( "@com_github_prysmaticlabs_fastssz//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", "@io_opencensus_go//trace:go_default_library", + "@org_golang_google_protobuf//proto:go_default_library", ], ) @@ -49,6 +51,7 @@ go_test( "//math:go_default_library", "//proto/engine/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", + "//runtime/version:go_default_library", "//testing/assert:go_default_library", "//testing/require:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", diff --git a/api/client/builder/client.go b/api/client/builder/client.go index b9709abcd9a0..ba7c33328f36 100644 --- a/api/client/builder/client.go +++ b/api/client/builder/client.go @@ -6,7 +6,6 @@ import ( "encoding/json" "fmt" "io" - "math/big" "net" "net/http" "net/url" @@ -14,11 +13,11 @@ import ( "text/template" "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v5/api" "github.com/prysmaticlabs/prysm/v5/api/server/structs" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" - "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" v1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" @@ -282,133 +281,68 @@ func (c *Client) RegisterValidator(ctx context.Context, svr []*ethpb.SignedValid return err } +var errResponseVersionMismatch = errors.New("builder API response uses a different version than requested in " + api.VersionHeader + " header") + // SubmitBlindedBlock calls the builder API endpoint that binds the validator to the builder and submits the block. // The response is the full execution payload used to create the blinded block. func (c *Client) SubmitBlindedBlock(ctx context.Context, sb interfaces.ReadOnlySignedBeaconBlock) (interfaces.ExecutionData, *v1.BlobsBundle, error) { if !sb.IsBlinded() { return nil, nil, errNotBlinded } - switch sb.Version() { - case version.Bellatrix: - psb, err := sb.PbBlindedBellatrixBlock() - if err != nil { - return nil, nil, errors.Wrapf(err, "could not get protobuf block") - } - b, err := structs.SignedBlindedBeaconBlockBellatrixFromConsensus(ðpb.SignedBlindedBeaconBlockBellatrix{Block: psb.Block, Signature: bytesutil.SafeCopyBytes(psb.Signature)}) - if err != nil { - return nil, nil, errors.Wrapf(err, "could not convert SignedBlindedBeaconBlockBellatrix to json marshalable type") - } - body, err := json.Marshal(b) - if err != nil { - return nil, nil, errors.Wrap(err, "error encoding the SignedBlindedBeaconBlockBellatrix value body in SubmitBlindedBlock") - } - versionOpt := func(r *http.Request) { - r.Header.Add("Eth-Consensus-Version", version.String(version.Bellatrix)) - r.Header.Set("Content-Type", "application/json") - r.Header.Set("Accept", "application/json") - } - rb, err := c.do(ctx, http.MethodPost, postBlindedBeaconBlockPath, bytes.NewBuffer(body), versionOpt) - if err != nil { - return nil, nil, errors.Wrap(err, "error posting the SignedBlindedBeaconBlockBellatrix to the builder api") - } - ep := &ExecPayloadResponse{} - if err := json.Unmarshal(rb, ep); err != nil { - return nil, nil, errors.Wrap(err, "error unmarshaling the builder SubmitBlindedBlock response") - } - if strings.ToLower(ep.Version) != version.String(version.Bellatrix) { - return nil, nil, errors.New("not a bellatrix payload") - } - p, err := ep.ToProto() - if err != nil { - return nil, nil, errors.Wrapf(err, "could not extract proto message from payload") - } - payload, err := blocks.WrappedExecutionPayload(p) - if err != nil { - return nil, nil, errors.Wrapf(err, "could not wrap execution payload in interface") - } - return payload, nil, nil - case version.Capella: - psb, err := sb.PbBlindedCapellaBlock() - if err != nil { - return nil, nil, errors.Wrapf(err, "could not get protobuf block") - } - b, err := structs.SignedBlindedBeaconBlockCapellaFromConsensus(ðpb.SignedBlindedBeaconBlockCapella{Block: psb.Block, Signature: bytesutil.SafeCopyBytes(psb.Signature)}) - if err != nil { - return nil, nil, errors.Wrapf(err, "could not convert SignedBlindedBeaconBlockCapella to json marshalable type") - } - body, err := json.Marshal(b) - if err != nil { - return nil, nil, errors.Wrap(err, "error encoding the SignedBlindedBeaconBlockCapella value body in SubmitBlindedBlockCapella") - } - versionOpt := func(r *http.Request) { - r.Header.Add("Eth-Consensus-Version", version.String(version.Capella)) - r.Header.Set("Content-Type", "application/json") - r.Header.Set("Accept", "application/json") - } - rb, err := c.do(ctx, http.MethodPost, postBlindedBeaconBlockPath, bytes.NewBuffer(body), versionOpt) - - if err != nil { - return nil, nil, errors.Wrap(err, "error posting the SignedBlindedBeaconBlockCapella to the builder api") - } - ep := &ExecPayloadResponseCapella{} - if err := json.Unmarshal(rb, ep); err != nil { - return nil, nil, errors.Wrap(err, "error unmarshaling the builder SubmitBlindedBlockCapella response") - } - if strings.ToLower(ep.Version) != version.String(version.Capella) { - return nil, nil, errors.New("not a capella payload") - } - p, err := ep.ToProto() - if err != nil { - return nil, nil, errors.Wrapf(err, "could not extract proto message from payload") - } - payload, err := blocks.WrappedExecutionPayloadCapella(p, big.NewInt(0)) - if err != nil { - return nil, nil, errors.Wrapf(err, "could not wrap execution payload in interface") - } - return payload, nil, nil - case version.Deneb: - psb, err := sb.PbBlindedDenebBlock() - if err != nil { - return nil, nil, errors.Wrapf(err, "could not get protobuf block") - } - b, err := structs.SignedBlindedBeaconBlockDenebFromConsensus(ðpb.SignedBlindedBeaconBlockDeneb{Message: psb.Message, Signature: bytesutil.SafeCopyBytes(psb.Signature)}) - if err != nil { - return nil, nil, errors.Wrapf(err, "could not convert SignedBlindedBeaconBlockDeneb to json marshalable type") - } - body, err := json.Marshal(b) - if err != nil { - return nil, nil, errors.Wrap(err, "error encoding the SignedBlindedBeaconBlockDeneb value body in SubmitBlindedBlockDeneb") - } + // massage the proto struct type data into the api response type. + mj, err := structs.SignedBeaconBlockMessageJsoner(sb) + if err != nil { + return nil, nil, errors.Wrap(err, "error generating blinded beacon block post request") + } - versionOpt := func(r *http.Request) { - r.Header.Add("Eth-Consensus-Version", version.String(version.Deneb)) - r.Header.Set("Content-Type", "application/json") - r.Header.Set("Accept", "application/json") - } - rb, err := c.do(ctx, http.MethodPost, postBlindedBeaconBlockPath, bytes.NewBuffer(body), versionOpt) - if err != nil { - return nil, nil, errors.Wrap(err, "error posting the SignedBlindedBeaconBlockDeneb to the builder api") - } - ep := &ExecPayloadResponseDeneb{} - if err := json.Unmarshal(rb, ep); err != nil { - return nil, nil, errors.Wrap(err, "error unmarshaling the builder SubmitBlindedBlockDeneb response") - } - if strings.ToLower(ep.Version) != version.String(version.Deneb) { - return nil, nil, errors.New("not a deneb payload") - } - p, blobBundle, err := ep.ToProto() - if err != nil { - return nil, nil, errors.Wrapf(err, "could not extract proto message from payload") - } - payload, err := blocks.WrappedExecutionPayloadDeneb(p, big.NewInt(0)) + body, err := json.Marshal(mj) + if err != nil { + return nil, nil, errors.Wrap(err, "error marshaling blinded block post request to json") + } + postOpts := func(r *http.Request) { + r.Header.Add("Eth-Consensus-Version", version.String(sb.Version())) + r.Header.Set("Content-Type", api.JsonMediaType) + r.Header.Set("Accept", api.JsonMediaType) + } + // post the blinded block - the execution payload response should contain the unblinded payload, along with the + // blobs bundle if it is post deneb. + rb, err := c.do(ctx, http.MethodPost, postBlindedBeaconBlockPath, bytes.NewBuffer(body), postOpts) + if err != nil { + return nil, nil, errors.Wrap(err, "error posting the blinded block to the builder api") + } + // ExecutionPayloadResponse parses just the outer container and the Value key, enabling it to use the .Value + // key to determine which underlying data type to use to finish the unmarshaling. + ep := &ExecutionPayloadResponse{} + if err := json.Unmarshal(rb, ep); err != nil { + return nil, nil, errors.Wrap(err, "error unmarshaling the builder ExecutionPayloadResponse") + } + if strings.ToLower(ep.Version) != version.String(sb.Version()) { + return nil, nil, errors.Wrapf(errResponseVersionMismatch, "req=%s, recv=%s", strings.ToLower(ep.Version), version.String(sb.Version())) + } + // This parses the rest of the response and returns the inner data field. + pp, err := ep.ParsePayload() + if err != nil { + return nil, nil, errors.Wrapf(err, "failed to parse execution payload from builder with version=%s", ep.Version) + } + // Get the payload as a proto.Message so it can be wrapped as an execution payload interface. + pb, err := pp.PayloadProto() + if err != nil { + return nil, nil, err + } + ed, err := blocks.NewWrappedExecutionData(pb, nil) + if err != nil { + return nil, nil, err + } + bb, ok := pp.(BlobBundler) + if ok { + bbpb, err := bb.BundleProto() if err != nil { - return nil, nil, errors.Wrapf(err, "could not wrap execution payload in interface") + return nil, nil, errors.Wrapf(err, "failed to extract blobs bundle from builder response with version=%s", ep.Version) } - return payload, blobBundle, nil - default: - return nil, nil, fmt.Errorf("unsupported block version %s", version.String(sb.Version())) + return ed, bbpb, nil } + return ed, nil, nil } // Status asks the remote builder server for a health check. A response of 200 with an empty body is the success/healthy diff --git a/api/client/builder/client_test.go b/api/client/builder/client_test.go index 5131ec716317..eaa8f1f53068 100644 --- a/api/client/builder/client_test.go +++ b/api/client/builder/client_test.go @@ -432,7 +432,7 @@ func TestSubmitBlindedBlock(t *testing.T) { sbbb, err := blocks.NewSignedBeaconBlock(testSignedBlindedBeaconBlockBellatrix(t)) require.NoError(t, err) _, _, err = c.SubmitBlindedBlock(ctx, sbbb) - require.ErrorContains(t, "not a bellatrix payload", err) + require.ErrorIs(t, err, errResponseVersionMismatch) }) t.Run("not blinded", func(t *testing.T) { sbb, err := blocks.NewSignedBeaconBlock(ð.SignedBeaconBlockBellatrix{Block: ð.BeaconBlockBellatrix{Body: ð.BeaconBlockBodyBellatrix{ExecutionPayload: &v1.ExecutionPayload{}}}}) diff --git a/api/client/builder/types.go b/api/client/builder/types.go index 214e5b729837..29905096739d 100644 --- a/api/client/builder/types.go +++ b/api/client/builder/types.go @@ -9,11 +9,15 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/pkg/errors" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" + consensusblocks "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" + "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" types "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/math" v1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + "google.golang.org/protobuf/proto" ) var errInvalidUint256 = errors.New("invalid Uint256") @@ -44,6 +48,9 @@ func sszBytesToUint256(b []byte) (Uint256, error) { // SSZBytes creates an ssz-style (little-endian byte slice) representation of the Uint256. func (s Uint256) SSZBytes() []byte { + if s.Int == nil { + s.Int = big.NewInt(0) + } if !math.IsValidUint256(s.Int) { return []byte{} } @@ -91,6 +98,9 @@ func (s Uint256) MarshalJSON() ([]byte, error) { // MarshalText returns a text byte representation of Uint256. func (s Uint256) MarshalText() ([]byte, error) { + if s.Int == nil { + s.Int = big.NewInt(0) + } if !math.IsValidUint256(s.Int) { return nil, errors.Wrapf(errInvalidUint256, "value=%s", s.Int) } @@ -265,6 +275,11 @@ func (r *ExecPayloadResponse) ToProto() (*v1.ExecutionPayload, error) { return r.Data.ToProto() } +func (r *ExecutionPayload) PayloadProto() (proto.Message, error) { + pb, err := r.ToProto() + return pb, err +} + // ToProto returns a ExecutionPayload Proto func (p *ExecutionPayload) ToProto() (*v1.ExecutionPayload, error) { txs := make([][]byte, len(p.Transactions)) @@ -396,6 +411,51 @@ func FromProtoDeneb(payload *v1.ExecutionPayloadDeneb) (ExecutionPayloadDeneb, e }, nil } +var errInvalidTypeConversion = errors.New("unable to translate between api and foreign type") + +// ExecutionPayloadResponseFromData converts an ExecutionData interface value to a payload response. +// This involves serializing the execution payload value so that the abstract payload envelope can be used. +func ExecutionPayloadResponseFromData(ed interfaces.ExecutionData, bundle *v1.BlobsBundle) (*ExecutionPayloadResponse, error) { + pb := ed.Proto() + var data interface{} + var err error + var ver string + switch pbStruct := pb.(type) { + case *v1.ExecutionPayload: + ver = version.String(version.Bellatrix) + data, err = FromProto(pbStruct) + if err != nil { + return nil, errors.Wrap(err, "failed to convert a Bellatrix ExecutionPayload to an API response") + } + case *v1.ExecutionPayloadCapella: + ver = version.String(version.Capella) + data, err = FromProtoCapella(pbStruct) + if err != nil { + return nil, errors.Wrap(err, "failed to convert a Capella ExecutionPayload to an API response") + } + case *v1.ExecutionPayloadDeneb: + ver = version.String(version.Deneb) + payloadStruct, err := FromProtoDeneb(pbStruct) + if err != nil { + return nil, errors.Wrap(err, "failed to convert a Deneb ExecutionPayload to an API response") + } + data = &ExecutionPayloadDenebAndBlobsBundle{ + ExecutionPayload: &payloadStruct, + BlobsBundle: FromBundleProto(bundle), + } + default: + return nil, errInvalidTypeConversion + } + encoded, err := json.Marshal(data) + if err != nil { + return nil, errors.Wrapf(err, "failed to marshal execution payload version=%s", ver) + } + return &ExecutionPayloadResponse{ + Version: ver, + Data: encoded, + }, nil +} + // ExecHeaderResponseCapella is the response of builder API /eth/v1/builder/header/{slot}/{parent_hash}/{pubkey} for Capella. type ExecHeaderResponseCapella struct { Data struct { @@ -523,6 +583,42 @@ type ExecPayloadResponseCapella struct { Data ExecutionPayloadCapella `json:"data"` } +// ExecutionPayloadResponse allows for unmarshaling just the Version field of the payload. +// This allows it to return different ExecutionPayload types based on the version field. +type ExecutionPayloadResponse struct { + Version string `json:"version"` + Data json.RawMessage `json:"data"` +} + +// ParsedPayload can retrieve the underlying protobuf message for the given execution payload response. +type ParsedPayload interface { + PayloadProto() (proto.Message, error) +} + +// BlobBundler can retrieve the underlying blob bundle protobuf message for the given execution payload response. +type BlobBundler interface { + BundleProto() (*v1.BlobsBundle, error) +} + +func (r *ExecutionPayloadResponse) ParsePayload() (ParsedPayload, error) { + var toProto ParsedPayload + switch r.Version { + case version.String(version.Bellatrix): + toProto = &ExecutionPayload{} + case version.String(version.Capella): + toProto = &ExecutionPayloadCapella{} + case version.String(version.Deneb): + toProto = &ExecutionPayloadDenebAndBlobsBundle{} + default: + return nil, consensusblocks.ErrUnsupportedVersion + } + + if err := json.Unmarshal(r.Data, toProto); err != nil { + return nil, errors.Wrap(err, "failed to unmarshal the response .Data field with the stated version schema") + } + return toProto, nil +} + // ExecutionPayloadCapella is a field of ExecPayloadResponseCapella. type ExecutionPayloadCapella struct { ParentHash hexutil.Bytes `json:"parent_hash"` @@ -547,6 +643,11 @@ func (r *ExecPayloadResponseCapella) ToProto() (*v1.ExecutionPayloadCapella, err return r.Data.ToProto() } +func (p *ExecutionPayloadCapella) PayloadProto() (proto.Message, error) { + pb, err := p.ToProto() + return pb, err +} + // ToProto returns a ExecutionPayloadCapella Proto. func (p *ExecutionPayloadCapella) ToProto() (*v1.ExecutionPayloadCapella, error) { txs := make([][]byte, len(p.Transactions)) @@ -1128,6 +1229,12 @@ func (r *ExecPayloadResponseDeneb) ToProto() (*v1.ExecutionPayloadDeneb, *v1.Blo if r.Data == nil { return nil, nil, errors.New("data field in response is empty") } + if r.Data.ExecutionPayload == nil { + return nil, nil, errors.Wrap(consensusblocks.ErrNilObject, "nil execution payload") + } + if r.Data.BlobsBundle == nil { + return nil, nil, errors.Wrap(consensusblocks.ErrNilObject, "nil blobs bundle") + } payload, err := r.Data.ExecutionPayload.ToProto() if err != nil { return nil, nil, err @@ -1139,8 +1246,26 @@ func (r *ExecPayloadResponseDeneb) ToProto() (*v1.ExecutionPayloadDeneb, *v1.Blo return payload, bundle, nil } +func (r *ExecutionPayloadDenebAndBlobsBundle) PayloadProto() (proto.Message, error) { + if r.ExecutionPayload == nil { + return nil, errors.Wrap(consensusblocks.ErrNilObject, "nil execution payload in combined deneb payload") + } + pb, err := r.ExecutionPayload.ToProto() + return pb, err +} + +func (r *ExecutionPayloadDenebAndBlobsBundle) BundleProto() (*v1.BlobsBundle, error) { + if r.BlobsBundle == nil { + return nil, errors.Wrap(consensusblocks.ErrNilObject, "nil blobs bundle") + } + return r.BlobsBundle.ToProto() +} + // ToProto returns the ExecutionPayloadDeneb Proto. func (p *ExecutionPayloadDeneb) ToProto() (*v1.ExecutionPayloadDeneb, error) { + if p == nil { + return nil, errors.Wrap(consensusblocks.ErrNilObject, "nil execution payload") + } txs := make([][]byte, len(p.Transactions)) for i := range p.Transactions { txs[i] = bytesutil.SafeCopyBytes(p.Transactions[i]) diff --git a/api/client/builder/types_test.go b/api/client/builder/types_test.go index 33efeac394d4..0bc6b1b57c50 100644 --- a/api/client/builder/types_test.go +++ b/api/client/builder/types_test.go @@ -15,9 +15,11 @@ import ( "github.com/prysmaticlabs/go-bitfield" "github.com/prysmaticlabs/prysm/v5/api/server/structs" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" + consensusblocks "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/math" v1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/testing/assert" "github.com/prysmaticlabs/prysm/v5/testing/require" ) @@ -1600,7 +1602,6 @@ func TestBuilderBidUnmarshalUint256(t *testing.T) { require.NoError(t, expectedValue.UnmarshalText([]byte(base10))) r := &ExecHeaderResponse{} require.NoError(t, json.Unmarshal([]byte(testBuilderBid), r)) - //require.Equal(t, expectedValue, r.Data.Message.Value) marshaled := r.Data.Message.Value.String() require.Equal(t, base10, marshaled) require.Equal(t, 0, expectedValue.Cmp(r.Data.Message.Value.Int)) @@ -1907,3 +1908,40 @@ func TestErrorMessage_non200Err(t *testing.T) { }) } } + +func TestEmptyResponseBody(t *testing.T) { + t.Run("empty buffer", func(t *testing.T) { + var b []byte + r := &ExecutionPayloadResponse{} + err := json.Unmarshal(b, r) + _, ok := err.(*json.SyntaxError) + require.Equal(t, true, ok) + }) + t.Run("empty object", func(t *testing.T) { + empty := []byte("{}") + emptyResponse := &ExecutionPayloadResponse{} + require.NoError(t, json.Unmarshal(empty, emptyResponse)) + _, err := emptyResponse.ParsePayload() + require.ErrorIs(t, err, consensusblocks.ErrUnsupportedVersion) + }) + versions := []int{version.Bellatrix, version.Capella, version.Deneb} + for i := range versions { + vstr := version.String(versions[i]) + t.Run("populated version without payload"+vstr, func(t *testing.T) { + in := &ExecutionPayloadResponse{Version: vstr} + encoded, err := json.Marshal(in) + require.NoError(t, err) + epr := &ExecutionPayloadResponse{} + require.NoError(t, json.Unmarshal(encoded, epr)) + pp, err := epr.ParsePayload() + require.NoError(t, err) + pb, err := pp.PayloadProto() + if err == nil { + require.NoError(t, err) + require.Equal(t, false, pb == nil) + } else { + require.ErrorIs(t, err, consensusblocks.ErrNilObject) + } + }) + } +} diff --git a/api/server/structs/BUILD.bazel b/api/server/structs/BUILD.bazel index 7727a44f1b89..df11af3b0221 100644 --- a/api/server/structs/BUILD.bazel +++ b/api/server/structs/BUILD.bazel @@ -26,6 +26,7 @@ go_library( "//api/server:go_default_library", "//beacon-chain/state:go_default_library", "//config/fieldparams:go_default_library", + "//consensus-types/interfaces:go_default_library", "//consensus-types/primitives:go_default_library", "//consensus-types/validator:go_default_library", "//container/slice:go_default_library", diff --git a/api/server/structs/block.go b/api/server/structs/block.go index b5cfc1f27d1b..7615f3653a4e 100644 --- a/api/server/structs/block.go +++ b/api/server/structs/block.go @@ -1,10 +1,34 @@ package structs +import "encoding/json" + +// MessageJsoner describes a signed consensus type wrapper that can return the `.Message` field in a json envelope +// encoded as a []byte, for use as a json.RawMessage value when encoding the outer envelope. +type MessageJsoner interface { + MessageRawJson() ([]byte, error) +} + +// SignedMessageJsoner embeds MessageJsoner and adds a method to also retrieve the Signature field as a string. +type SignedMessageJsoner interface { + MessageJsoner + SigString() string +} + type SignedBeaconBlock struct { Message *BeaconBlock `json:"message"` Signature string `json:"signature"` } +var _ SignedMessageJsoner = &SignedBeaconBlock{} + +func (s *SignedBeaconBlock) MessageRawJson() ([]byte, error) { + return json.Marshal(s.Message) +} + +func (s *SignedBeaconBlock) SigString() string { + return s.Signature +} + type BeaconBlock struct { Slot string `json:"slot"` ProposerIndex string `json:"proposer_index"` @@ -29,6 +53,16 @@ type SignedBeaconBlockAltair struct { Signature string `json:"signature"` } +var _ SignedMessageJsoner = &SignedBeaconBlockAltair{} + +func (s *SignedBeaconBlockAltair) MessageRawJson() ([]byte, error) { + return json.Marshal(s.Message) +} + +func (s *SignedBeaconBlockAltair) SigString() string { + return s.Signature +} + type BeaconBlockAltair struct { Slot string `json:"slot"` ProposerIndex string `json:"proposer_index"` @@ -54,6 +88,16 @@ type SignedBeaconBlockBellatrix struct { Signature string `json:"signature"` } +var _ SignedMessageJsoner = &SignedBeaconBlockBellatrix{} + +func (s *SignedBeaconBlockBellatrix) MessageRawJson() ([]byte, error) { + return json.Marshal(s.Message) +} + +func (s *SignedBeaconBlockBellatrix) SigString() string { + return s.Signature +} + type BeaconBlockBellatrix struct { Slot string `json:"slot"` ProposerIndex string `json:"proposer_index"` @@ -80,6 +124,16 @@ type SignedBlindedBeaconBlockBellatrix struct { Signature string `json:"signature"` } +var _ SignedMessageJsoner = &SignedBlindedBeaconBlockBellatrix{} + +func (s *SignedBlindedBeaconBlockBellatrix) MessageRawJson() ([]byte, error) { + return json.Marshal(s.Message) +} + +func (s *SignedBlindedBeaconBlockBellatrix) SigString() string { + return s.Signature +} + type BlindedBeaconBlockBellatrix struct { Slot string `json:"slot"` ProposerIndex string `json:"proposer_index"` @@ -106,6 +160,16 @@ type SignedBeaconBlockCapella struct { Signature string `json:"signature"` } +var _ SignedMessageJsoner = &SignedBeaconBlockCapella{} + +func (s *SignedBeaconBlockCapella) MessageRawJson() ([]byte, error) { + return json.Marshal(s.Message) +} + +func (s *SignedBeaconBlockCapella) SigString() string { + return s.Signature +} + type BeaconBlockCapella struct { Slot string `json:"slot"` ProposerIndex string `json:"proposer_index"` @@ -133,6 +197,16 @@ type SignedBlindedBeaconBlockCapella struct { Signature string `json:"signature"` } +var _ SignedMessageJsoner = &SignedBlindedBeaconBlockCapella{} + +func (s *SignedBlindedBeaconBlockCapella) MessageRawJson() ([]byte, error) { + return json.Marshal(s.Message) +} + +func (s *SignedBlindedBeaconBlockCapella) SigString() string { + return s.Signature +} + type BlindedBeaconBlockCapella struct { Slot string `json:"slot"` ProposerIndex string `json:"proposer_index"` @@ -172,6 +246,16 @@ type SignedBeaconBlockDeneb struct { Signature string `json:"signature"` } +var _ SignedMessageJsoner = &SignedBeaconBlockDeneb{} + +func (s *SignedBeaconBlockDeneb) MessageRawJson() ([]byte, error) { + return json.Marshal(s.Message) +} + +func (s *SignedBeaconBlockDeneb) SigString() string { + return s.Signature +} + type BeaconBlockDeneb struct { Slot string `json:"slot"` ProposerIndex string `json:"proposer_index"` @@ -208,6 +292,16 @@ type SignedBlindedBeaconBlockDeneb struct { Signature string `json:"signature"` } +var _ SignedMessageJsoner = &SignedBlindedBeaconBlockDeneb{} + +func (s *SignedBlindedBeaconBlockDeneb) MessageRawJson() ([]byte, error) { + return json.Marshal(s.Message) +} + +func (s *SignedBlindedBeaconBlockDeneb) SigString() string { + return s.Signature +} + type BlindedBeaconBlockBodyDeneb struct { RandaoReveal string `json:"randao_reveal"` Eth1Data *Eth1Data `json:"eth1_data"` diff --git a/api/server/structs/conversions_block.go b/api/server/structs/conversions_block.go index 4349d7d46ddc..6a3f4e912997 100644 --- a/api/server/structs/conversions_block.go +++ b/api/server/structs/conversions_block.go @@ -6,8 +6,10 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/api/server" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" + "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/container/slice" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" @@ -15,6 +17,8 @@ import ( eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" ) +var ErrUnsupportedConversion = errors.New("Could not determine api struct type to use for value") + func (h *SignedBeaconBlockHeader) ToConsensus() (*eth.SignedBeaconBlockHeader, error) { msg, err := h.Message.ToConsensus() if err != nil { @@ -1852,7 +1856,34 @@ func BeaconBlockFromConsensus(b *eth.BeaconBlock) *BeaconBlock { } } -func SignedBeaconBlockFromConsensus(b *eth.SignedBeaconBlock) *SignedBeaconBlock { +func SignedBeaconBlockMessageJsoner(block interfaces.ReadOnlySignedBeaconBlock) (SignedMessageJsoner, error) { + pb, err := block.Proto() + if err != nil { + return nil, err + } + switch pbStruct := pb.(type) { + case *eth.SignedBeaconBlock: + return SignedBeaconBlockPhase0FromConsensus(pbStruct), nil + case *eth.SignedBeaconBlockAltair: + return SignedBeaconBlockAltairFromConsensus(pbStruct), nil + case *eth.SignedBlindedBeaconBlockBellatrix: + return SignedBlindedBeaconBlockBellatrixFromConsensus(pbStruct) + case *eth.SignedBeaconBlockBellatrix: + return SignedBeaconBlockBellatrixFromConsensus(pbStruct) + case *eth.SignedBlindedBeaconBlockCapella: + return SignedBlindedBeaconBlockCapellaFromConsensus(pbStruct) + case *eth.SignedBeaconBlockCapella: + return SignedBeaconBlockCapellaFromConsensus(pbStruct) + case *eth.SignedBlindedBeaconBlockDeneb: + return SignedBlindedBeaconBlockDenebFromConsensus(pbStruct) + case *eth.SignedBeaconBlockDeneb: + return SignedBeaconBlockDenebFromConsensus(pbStruct) + default: + return nil, ErrUnsupportedConversion + } +} + +func SignedBeaconBlockPhase0FromConsensus(b *eth.SignedBeaconBlock) *SignedBeaconBlock { return &SignedBeaconBlock{ Message: BeaconBlockFromConsensus(b.Block), Signature: hexutil.Encode(b.Signature), diff --git a/beacon-chain/db/kv/BUILD.bazel b/beacon-chain/db/kv/BUILD.bazel index a1995e31e47f..464a6c82e196 100644 --- a/beacon-chain/db/kv/BUILD.bazel +++ b/beacon-chain/db/kv/BUILD.bazel @@ -115,6 +115,7 @@ go_test( "//proto/engine/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//proto/testing:go_default_library", + "//runtime/version:go_default_library", "//testing/assert:go_default_library", "//testing/require:go_default_library", "//testing/util:go_default_library", diff --git a/beacon-chain/db/kv/blocks_test.go b/beacon-chain/db/kv/blocks_test.go index 67235b2aef41..03bd37dfad5a 100644 --- a/beacon-chain/db/kv/blocks_test.go +++ b/beacon-chain/db/kv/blocks_test.go @@ -14,6 +14,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/testing/assert" "github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/testing/util" @@ -180,7 +181,7 @@ func TestStore_BlocksCRUD(t *testing.T) { retrievedBlock, err = db.Block(ctx, blockRoot) require.NoError(t, err) wanted := retrievedBlock - if _, err := retrievedBlock.PbBellatrixBlock(); err == nil { + if retrievedBlock.Version() >= version.Bellatrix { wanted, err = retrievedBlock.ToBlinded() require.NoError(t, err) } @@ -368,15 +369,7 @@ func TestStore_BlocksCRUD_NoCache(t *testing.T) { require.NoError(t, err) wanted := blk - if _, err := blk.PbBellatrixBlock(); err == nil { - wanted, err = blk.ToBlinded() - require.NoError(t, err) - } - if _, err := blk.PbCapellaBlock(); err == nil { - wanted, err = blk.ToBlinded() - require.NoError(t, err) - } - if _, err := blk.PbDenebBlock(); err == nil { + if blk.Version() >= version.Bellatrix { wanted, err = blk.ToBlinded() require.NoError(t, err) } @@ -595,15 +588,7 @@ func TestStore_SaveBlock_CanGetHighestAt(t *testing.T) { b, err := db.Block(ctx, root) require.NoError(t, err) wanted := block1 - if _, err := block1.PbBellatrixBlock(); err == nil { - wanted, err = wanted.ToBlinded() - require.NoError(t, err) - } - if _, err := block1.PbCapellaBlock(); err == nil { - wanted, err = wanted.ToBlinded() - require.NoError(t, err) - } - if _, err := block1.PbDenebBlock(); err == nil { + if block1.Version() >= version.Bellatrix { wanted, err = wanted.ToBlinded() require.NoError(t, err) } @@ -621,15 +606,7 @@ func TestStore_SaveBlock_CanGetHighestAt(t *testing.T) { b, err = db.Block(ctx, root) require.NoError(t, err) wanted2 := block2 - if _, err := block2.PbBellatrixBlock(); err == nil { - wanted2, err = block2.ToBlinded() - require.NoError(t, err) - } - if _, err := block2.PbCapellaBlock(); err == nil { - wanted2, err = block2.ToBlinded() - require.NoError(t, err) - } - if _, err := block2.PbDenebBlock(); err == nil { + if block2.Version() >= version.Bellatrix { wanted2, err = block2.ToBlinded() require.NoError(t, err) } @@ -647,15 +624,7 @@ func TestStore_SaveBlock_CanGetHighestAt(t *testing.T) { b, err = db.Block(ctx, root) require.NoError(t, err) wanted = block3 - if _, err := block3.PbBellatrixBlock(); err == nil { - wanted, err = wanted.ToBlinded() - require.NoError(t, err) - } - if _, err := block3.PbCapellaBlock(); err == nil { - wanted, err = wanted.ToBlinded() - require.NoError(t, err) - } - if _, err := block3.PbDenebBlock(); err == nil { + if block3.Version() >= version.Bellatrix { wanted, err = wanted.ToBlinded() require.NoError(t, err) } @@ -691,15 +660,7 @@ func TestStore_GenesisBlock_CanGetHighestAt(t *testing.T) { b, err := db.Block(ctx, root) require.NoError(t, err) wanted := block1 - if _, err := block1.PbBellatrixBlock(); err == nil { - wanted, err = block1.ToBlinded() - require.NoError(t, err) - } - if _, err := block1.PbCapellaBlock(); err == nil { - wanted, err = block1.ToBlinded() - require.NoError(t, err) - } - if _, err := block1.PbDenebBlock(); err == nil { + if block1.Version() >= version.Bellatrix { wanted, err = block1.ToBlinded() require.NoError(t, err) } @@ -716,15 +677,7 @@ func TestStore_GenesisBlock_CanGetHighestAt(t *testing.T) { b, err = db.Block(ctx, root) require.NoError(t, err) wanted = genesisBlock - if _, err := genesisBlock.PbBellatrixBlock(); err == nil { - wanted, err = genesisBlock.ToBlinded() - require.NoError(t, err) - } - if _, err := genesisBlock.PbCapellaBlock(); err == nil { - wanted, err = genesisBlock.ToBlinded() - require.NoError(t, err) - } - if _, err := genesisBlock.PbDenebBlock(); err == nil { + if genesisBlock.Version() >= version.Bellatrix { wanted, err = genesisBlock.ToBlinded() require.NoError(t, err) } @@ -741,15 +694,7 @@ func TestStore_GenesisBlock_CanGetHighestAt(t *testing.T) { b, err = db.Block(ctx, root) require.NoError(t, err) wanted = genesisBlock - if _, err := genesisBlock.PbBellatrixBlock(); err == nil { - wanted, err = genesisBlock.ToBlinded() - require.NoError(t, err) - } - if _, err := genesisBlock.PbCapellaBlock(); err == nil { - wanted, err = genesisBlock.ToBlinded() - require.NoError(t, err) - } - if _, err := genesisBlock.PbDenebBlock(); err == nil { + if genesisBlock.Version() >= version.Bellatrix { wanted, err = genesisBlock.ToBlinded() require.NoError(t, err) } @@ -845,15 +790,7 @@ func TestStore_BlocksBySlot_BlockRootsBySlot(t *testing.T) { require.NoError(t, err) wanted := b1 - if _, err := b1.PbBellatrixBlock(); err == nil { - wanted, err = b1.ToBlinded() - require.NoError(t, err) - } - if _, err := b1.PbCapellaBlock(); err == nil { - wanted, err = b1.ToBlinded() - require.NoError(t, err) - } - if _, err := b1.PbDenebBlock(); err == nil { + if b1.Version() >= version.Bellatrix { wanted, err = b1.ToBlinded() require.NoError(t, err) } @@ -869,15 +806,7 @@ func TestStore_BlocksBySlot_BlockRootsBySlot(t *testing.T) { t.Fatalf("Expected 2 blocks, received %d blocks", len(retrievedBlocks)) } wanted = b2 - if _, err := b2.PbBellatrixBlock(); err == nil { - wanted, err = b2.ToBlinded() - require.NoError(t, err) - } - if _, err := b2.PbCapellaBlock(); err == nil { - wanted, err = b2.ToBlinded() - require.NoError(t, err) - } - if _, err := b2.PbDenebBlock(); err == nil { + if b2.Version() >= version.Bellatrix { wanted, err = b2.ToBlinded() require.NoError(t, err) } @@ -887,15 +816,7 @@ func TestStore_BlocksBySlot_BlockRootsBySlot(t *testing.T) { require.NoError(t, err) assert.Equal(t, true, proto.Equal(wantedPb, retrieved0Pb), "Wanted: %v, received: %v", retrievedBlocks[0], wanted) wanted = b3 - if _, err := b3.PbBellatrixBlock(); err == nil { - wanted, err = b3.ToBlinded() - require.NoError(t, err) - } - if _, err := b3.PbCapellaBlock(); err == nil { - wanted, err = b3.ToBlinded() - require.NoError(t, err) - } - if _, err := b3.PbDenebBlock(); err == nil { + if b3.Version() >= version.Bellatrix { wanted, err = b3.ToBlinded() require.NoError(t, err) } diff --git a/beacon-chain/execution/engine_client_test.go b/beacon-chain/execution/engine_client_test.go index d7ef8d58762e..82296b5e5c32 100644 --- a/beacon-chain/execution/engine_client_test.go +++ b/beacon-chain/execution/engine_client_test.go @@ -16,7 +16,6 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" gethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/rpc" - gethRPC "github.com/ethereum/go-ethereum/rpc" "github.com/holiman/uint256" "github.com/pkg/errors" mocks "github.com/prysmaticlabs/prysm/v5/beacon-chain/execution/testing" @@ -45,7 +44,7 @@ type RPCClientBad struct { } func (RPCClientBad) Close() {} -func (RPCClientBad) BatchCall([]gethRPC.BatchElem) error { +func (RPCClientBad) BatchCall([]rpc.BatchElem) error { return errors.New("rpc client is not initialized") } @@ -76,7 +75,9 @@ func TestClient_IPC(t *testing.T) { resp, _, override, err := srv.GetPayload(ctx, payloadId, 1) require.NoError(t, err) require.Equal(t, false, override) - resPb, err := resp.PbBellatrix() + pbs := resp.Proto() + resPb, ok := pbs.(*pb.ExecutionPayload) + require.Equal(t, true, ok) require.NoError(t, err) require.DeepEqual(t, want, resPb) }) @@ -87,8 +88,9 @@ func TestClient_IPC(t *testing.T) { resp, _, override, err := srv.GetPayload(ctx, payloadId, params.BeaconConfig().SlotsPerEpoch) require.NoError(t, err) require.Equal(t, false, override) - resPb, err := resp.PbCapella() - require.NoError(t, err) + pbs := resp.Proto() + resPb, ok := pbs.(*pb.ExecutionPayloadCapella) + require.Equal(t, true, ok) require.DeepEqual(t, want, resPb) }) t.Run(ForkchoiceUpdatedMethod, func(t *testing.T) { @@ -201,9 +203,10 @@ func TestClient_HTTP(t *testing.T) { resp, _, override, err := client.GetPayload(ctx, payloadId, 1) require.NoError(t, err) require.Equal(t, false, override) - pb, err := resp.PbBellatrix() - require.NoError(t, err) - require.DeepEqual(t, want, pb) + pbs := resp.Proto() + pbStruct, ok := pbs.(*pb.ExecutionPayload) + require.Equal(t, true, ok) + require.DeepEqual(t, want, pbStruct) }) t.Run(GetPayloadMethodV2, func(t *testing.T) { payloadId := [8]byte{1} @@ -246,14 +249,15 @@ func TestClient_HTTP(t *testing.T) { resp, _, override, err := client.GetPayload(ctx, payloadId, params.BeaconConfig().SlotsPerEpoch) require.NoError(t, err) require.Equal(t, false, override) - pb, err := resp.PbCapella() - require.NoError(t, err) - require.DeepEqual(t, want.ExecutionPayload.BlockHash.Bytes(), pb.BlockHash) - require.DeepEqual(t, want.ExecutionPayload.StateRoot.Bytes(), pb.StateRoot) - require.DeepEqual(t, want.ExecutionPayload.ParentHash.Bytes(), pb.ParentHash) - require.DeepEqual(t, want.ExecutionPayload.FeeRecipient.Bytes(), pb.FeeRecipient) - require.DeepEqual(t, want.ExecutionPayload.PrevRandao.Bytes(), pb.PrevRandao) - require.DeepEqual(t, want.ExecutionPayload.ParentHash.Bytes(), pb.ParentHash) + pbs := resp.Proto() + ep, ok := pbs.(*pb.ExecutionPayloadCapella) + require.Equal(t, true, ok) + require.DeepEqual(t, want.ExecutionPayload.BlockHash.Bytes(), ep.BlockHash) + require.DeepEqual(t, want.ExecutionPayload.StateRoot.Bytes(), ep.StateRoot) + require.DeepEqual(t, want.ExecutionPayload.ParentHash.Bytes(), ep.ParentHash) + require.DeepEqual(t, want.ExecutionPayload.FeeRecipient.Bytes(), ep.FeeRecipient) + require.DeepEqual(t, want.ExecutionPayload.PrevRandao.Bytes(), ep.PrevRandao) + require.DeepEqual(t, want.ExecutionPayload.ParentHash.Bytes(), ep.ParentHash) v, err := resp.ValueInGwei() require.NoError(t, err) diff --git a/beacon-chain/rpc/eth/beacon/BUILD.bazel b/beacon-chain/rpc/eth/beacon/BUILD.bazel index 11ded5c96335..d9a8037e3e71 100644 --- a/beacon-chain/rpc/eth/beacon/BUILD.bazel +++ b/beacon-chain/rpc/eth/beacon/BUILD.bazel @@ -59,6 +59,7 @@ go_library( "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", "@com_github_gorilla_mux//:go_default_library", "@com_github_pkg_errors//:go_default_library", + "@com_github_prysmaticlabs_fastssz//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", "@io_opencensus_go//trace:go_default_library", ], diff --git a/beacon-chain/rpc/eth/beacon/handlers.go b/beacon-chain/rpc/eth/beacon/handlers.go index 7e446588ab9e..4fc48d4eac68 100644 --- a/beacon-chain/rpc/eth/beacon/handlers.go +++ b/beacon-chain/rpc/eth/beacon/handlers.go @@ -13,6 +13,7 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/gorilla/mux" "github.com/pkg/errors" + ssz "github.com/prysmaticlabs/fastssz" "github.com/prysmaticlabs/prysm/v5/api" "github.com/prysmaticlabs/prysm/v5/api/server/structs" "github.com/prysmaticlabs/prysm/v5/beacon-chain/cache/depositsnapshot" @@ -24,7 +25,6 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/prysm/v1alpha1/validator" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" - consensus_types "github.com/prysmaticlabs/prysm/v5/consensus-types" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" @@ -46,10 +46,9 @@ const ( var ( errNilBlock = errors.New("nil block") errEquivocatedBlock = errors.New("block is equivocated") + errMarshalSSZ = errors.New("could not marshal block into SSZ") ) -type handled bool - // GetBlockV2 retrieves block details for given block ID. func (s *Server) GetBlockV2(w http.ResponseWriter, r *http.Request) { ctx, span := trace.StartSpan(r.Context(), "beacon.GetBlockV2") @@ -61,93 +60,25 @@ func (s *Server) GetBlockV2(w http.ResponseWriter, r *http.Request) { return } blk, err := s.Blocker.Block(ctx, []byte(blockId)) - if !shared.WriteBlockFetchError(w, blk, err) { - return - } - - if httputil.RespondWithSsz(r) { - s.getBlockSSZV2(ctx, w, blk) - } else { - s.getBlockV2(ctx, w, blk) - } -} - -// getBlockV2 returns the JSON-serialized version of the beacon block for given block ID. -func (s *Server) getBlockV2(ctx context.Context, w http.ResponseWriter, blk interfaces.ReadOnlySignedBeaconBlock) { - blkRoot, err := blk.Block().HashTreeRoot() if err != nil { - httputil.HandleError(w, "Could not get block root "+err.Error(), http.StatusInternalServerError) - return - } - finalized := s.FinalizationFetcher.IsFinalized(ctx, blkRoot) - - getBlockHandler := func(get func(ctx context.Context, block interfaces.ReadOnlySignedBeaconBlock) (*structs.GetBlockV2Response, error)) handled { - result, err := get(ctx, blk) - if result != nil { - result.Finalized = finalized - w.Header().Set(api.VersionHeader, result.Version) - httputil.WriteJson(w, result) - return true - } - // ErrUnsupportedField means that we have another block type - if !errors.Is(err, consensus_types.ErrUnsupportedField) { - httputil.HandleError(w, "Could not get signed beacon block: "+err.Error(), http.StatusInternalServerError) - return true - } - return false - } - - if getBlockHandler(s.getBlockDeneb) { - return - } - if getBlockHandler(s.getBlockCapella) { - return - } - if getBlockHandler(s.getBlockBellatrix) { - return - } - if getBlockHandler(s.getBlockAltair) { - return - } - if getBlockHandler(s.getBlockPhase0) { + shared.WriteBlockFetchError(w, blk, err) return } - httputil.HandleError(w, fmt.Sprintf("Unknown block type %T", blk), http.StatusInternalServerError) -} -// getBlockSSZV2 returns the SSZ-serialized version of the beacon block for given block ID. -func (s *Server) getBlockSSZV2(ctx context.Context, w http.ResponseWriter, blk interfaces.ReadOnlySignedBeaconBlock) { - getBlockHandler := func(get func(ctx context.Context, block interfaces.ReadOnlySignedBeaconBlock) ([]byte, error), ver string) handled { - result, err := get(ctx, blk) - if result != nil { - w.Header().Set(api.VersionHeader, ver) - httputil.WriteSsz(w, result, "beacon_block.ssz") - return true - } - // ErrUnsupportedField means that we have another block type - if !errors.Is(err, consensus_types.ErrUnsupportedField) { - httputil.HandleError(w, "Could not get signed beacon block: "+err.Error(), http.StatusInternalServerError) - return true + // Deal with block unblinding. + if blk.Version() >= version.Bellatrix && blk.IsBlinded() { + blk, err = s.ExecutionPayloadReconstructor.ReconstructFullBlock(ctx, blk) + if err != nil { + shared.WriteBlockFetchError(w, blk, errors.Wrapf(err, "could not reconstruct full execution payload to create signed beacon block")) + return } - return false } - if getBlockHandler(s.getBlockDenebSSZ, version.String(version.Deneb)) { - return - } - if getBlockHandler(s.getBlockCapellaSSZ, version.String(version.Capella)) { - return - } - if getBlockHandler(s.getBlockBellatrixSSZ, version.String(version.Bellatrix)) { - return - } - if getBlockHandler(s.getBlockAltairSSZ, version.String(version.Altair)) { - return - } - if getBlockHandler(s.getBlockPhase0SSZ, version.String(version.Phase0)) { - return + if httputil.RespondWithSsz(r) { + s.getBlockV2Ssz(w, blk) + } else { + s.getBlockV2Json(ctx, w, blk) } - httputil.HandleError(w, fmt.Sprintf("Unknown block type %T", blk), http.StatusInternalServerError) } // GetBlindedBlock retrieves blinded block for given block id. @@ -165,701 +96,100 @@ func (s *Server) GetBlindedBlock(w http.ResponseWriter, r *http.Request) { return } - if httputil.RespondWithSsz(r) { - s.getBlindedBlockSSZ(ctx, w, blk) - } else { - s.getBlindedBlock(ctx, w, blk) - } -} - -// getBlindedBlock returns the JSON-serialized version of the blinded beacon block for given block id. -func (s *Server) getBlindedBlock(ctx context.Context, w http.ResponseWriter, blk interfaces.ReadOnlySignedBeaconBlock) { - blkRoot, err := blk.Block().HashTreeRoot() - if err != nil { - httputil.HandleError(w, "Could not get block root "+err.Error(), http.StatusInternalServerError) - return - } - finalized := s.FinalizationFetcher.IsFinalized(ctx, blkRoot) - - getBlockHandler := func(get func(ctx context.Context, block interfaces.ReadOnlySignedBeaconBlock) (*structs.GetBlockV2Response, error)) handled { - result, err := get(ctx, blk) - if result != nil { - result.Finalized = finalized - w.Header().Set(api.VersionHeader, result.Version) - httputil.WriteJson(w, result) - return true - } - // ErrUnsupportedField means that we have another block type - if !errors.Is(err, consensus_types.ErrUnsupportedField) { - httputil.HandleError(w, "Could not get signed beacon block: "+err.Error(), http.StatusInternalServerError) - return true - } - return false - } - - if getBlockHandler(s.getBlockPhase0) { - return - } - if getBlockHandler(s.getBlockAltair) { - return - } - if getBlockHandler(s.getBlindedBlockBellatrix) { - return - } - if getBlockHandler(s.getBlindedBlockCapella) { - return - } - if getBlockHandler(s.getBlindedBlockDeneb) { - return - } - httputil.HandleError(w, fmt.Sprintf("Unknown block type %T", blk), http.StatusInternalServerError) -} - -// getBlindedBlockSSZ returns the SSZ-serialized version of the blinded beacon block for given block id. -func (s *Server) getBlindedBlockSSZ(ctx context.Context, w http.ResponseWriter, blk interfaces.ReadOnlySignedBeaconBlock) { - getBlockHandler := func(get func(ctx context.Context, block interfaces.ReadOnlySignedBeaconBlock) ([]byte, error), ver string) handled { - result, err := get(ctx, blk) - if result != nil { - w.Header().Set(api.VersionHeader, ver) - httputil.WriteSsz(w, result, "beacon_block.ssz") - return true - } - // ErrUnsupportedField means that we have another block type - if !errors.Is(err, consensus_types.ErrUnsupportedField) { - httputil.HandleError(w, "Could not get signed beacon block: "+err.Error(), http.StatusInternalServerError) - return true - } - return false - } - - if getBlockHandler(s.getBlockPhase0SSZ, version.String(version.Phase0)) { - return - } - if getBlockHandler(s.getBlockAltairSSZ, version.String(version.Altair)) { - return - } - if getBlockHandler(s.getBlindedBlockBellatrixSSZ, version.String(version.Bellatrix)) { - return - } - if getBlockHandler(s.getBlindedBlockCapellaSSZ, version.String(version.Capella)) { - return - } - if getBlockHandler(s.getBlindedBlockDenebSSZ, version.String(version.Deneb)) { - return - } - httputil.HandleError(w, fmt.Sprintf("Unknown block type %T", blk), http.StatusInternalServerError) -} - -func (*Server) getBlockPhase0(_ context.Context, blk interfaces.ReadOnlySignedBeaconBlock) (*structs.GetBlockV2Response, error) { - consensusBlk, err := blk.PbPhase0Block() - if err != nil { - return nil, err - } - if consensusBlk == nil { - return nil, errNilBlock - } - respBlk := structs.SignedBeaconBlockFromConsensus(consensusBlk) - jsonBytes, err := json.Marshal(respBlk.Message) - if err != nil { - return nil, err - } - return &structs.GetBlockV2Response{ - Version: version.String(version.Phase0), - ExecutionOptimistic: false, - Data: &structs.SignedBlock{ - Message: jsonBytes, - Signature: respBlk.Signature, - }, - }, nil -} - -func (*Server) getBlockAltair(_ context.Context, blk interfaces.ReadOnlySignedBeaconBlock) (*structs.GetBlockV2Response, error) { - consensusBlk, err := blk.PbAltairBlock() - if err != nil { - return nil, err - } - if consensusBlk == nil { - return nil, errNilBlock - } - respBlk := structs.SignedBeaconBlockAltairFromConsensus(consensusBlk) - jsonBytes, err := json.Marshal(respBlk.Message) - if err != nil { - return nil, err - } - return &structs.GetBlockV2Response{ - Version: version.String(version.Altair), - ExecutionOptimistic: false, - Data: &structs.SignedBlock{ - Message: jsonBytes, - Signature: respBlk.Signature, - }, - }, nil -} - -func (s *Server) getBlockBellatrix(ctx context.Context, blk interfaces.ReadOnlySignedBeaconBlock) (*structs.GetBlockV2Response, error) { - consensusBlk, err := blk.PbBellatrixBlock() - if err != nil { - // ErrUnsupportedField means that we have another block type - if errors.Is(err, consensus_types.ErrUnsupportedField) { - blindedConsensusBlk, err := blk.PbBlindedBellatrixBlock() - if err != nil { - return nil, err - } - if blindedConsensusBlk == nil { - return nil, errNilBlock - } - fullBlk, err := s.ExecutionPayloadReconstructor.ReconstructFullBlock(ctx, blk) - if err != nil { - return nil, errors.Wrapf(err, "could not reconstruct full execution payload to create signed beacon block") - } - consensusBlk, err = fullBlk.PbBellatrixBlock() - if err != nil { - return nil, errors.Wrapf(err, "could not get signed beacon block") - } - } else { - return nil, err + // Convert to blinded block (if it's not already). + if blk.Version() >= version.Bellatrix && !blk.IsBlinded() { + blk, err = blk.ToBlinded() + if err != nil { + shared.WriteBlockFetchError(w, blk, errors.Wrapf(err, "could not convert block to blinded block")) + return } } - if consensusBlk == nil { - return nil, errNilBlock - } - root, err := blk.Block().HashTreeRoot() - if err != nil { - return nil, errors.Wrapf(err, "could not get block root") - } - isOptimistic, err := s.OptimisticModeFetcher.IsOptimisticForRoot(ctx, root) - if err != nil { - return nil, errors.Wrapf(err, "could not check if block is optimistic") - } - respBlk, err := structs.SignedBeaconBlockBellatrixFromConsensus(consensusBlk) - if err != nil { - return nil, err - } - jsonBytes, err := json.Marshal(respBlk.Message) - if err != nil { - return nil, err + if httputil.RespondWithSsz(r) { + s.getBlockV2Ssz(w, blk) + } else { + s.getBlockV2Json(ctx, w, blk) } - return &structs.GetBlockV2Response{ - Version: version.String(version.Bellatrix), - ExecutionOptimistic: isOptimistic, - Data: &structs.SignedBlock{ - Message: jsonBytes, - Signature: respBlk.Signature, - }, - }, nil } -func (s *Server) getBlockCapella(ctx context.Context, blk interfaces.ReadOnlySignedBeaconBlock) (*structs.GetBlockV2Response, error) { - consensusBlk, err := blk.PbCapellaBlock() - if err != nil { - // ErrUnsupportedField means that we have another block type - if errors.Is(err, consensus_types.ErrUnsupportedField) { - blindedConsensusBlk, err := blk.PbBlindedCapellaBlock() - if err != nil { - return nil, err - } - if blindedConsensusBlk == nil { - return nil, errNilBlock - } - fullBlk, err := s.ExecutionPayloadReconstructor.ReconstructFullBlock(ctx, blk) - if err != nil { - return nil, errors.Wrapf(err, "could not reconstruct full execution payload to create signed beacon block") - } - consensusBlk, err = fullBlk.PbCapellaBlock() - if err != nil { - return nil, errors.Wrapf(err, "could not get signed beacon block") - } - } else { - return nil, err - } - } - - if consensusBlk == nil { - return nil, errNilBlock - } - root, err := blk.Block().HashTreeRoot() +// getBlockV2Ssz returns the SSZ-serialized version of the beacon block for given block ID. +func (s *Server) getBlockV2Ssz(w http.ResponseWriter, blk interfaces.ReadOnlySignedBeaconBlock) { + result, err := s.getBlockResponseBodySsz(blk) if err != nil { - return nil, errors.Wrapf(err, "could not get block root") + httputil.HandleError(w, "Could not get signed beacon block: "+err.Error(), http.StatusInternalServerError) } - isOptimistic, err := s.OptimisticModeFetcher.IsOptimisticForRoot(ctx, root) - if err != nil { - return nil, errors.Wrapf(err, "could not check if block is optimistic") + if result == nil { + httputil.HandleError(w, fmt.Sprintf("Unknown block type %T", blk), http.StatusInternalServerError) } - respBlk, err := structs.SignedBeaconBlockCapellaFromConsensus(consensusBlk) - if err != nil { - return nil, err - } - jsonBytes, err := json.Marshal(respBlk.Message) - if err != nil { - return nil, err - } - return &structs.GetBlockV2Response{ - Version: version.String(version.Capella), - ExecutionOptimistic: isOptimistic, - Data: &structs.SignedBlock{ - Message: jsonBytes, - Signature: respBlk.Signature, - }, - }, nil + w.Header().Set(api.VersionHeader, version.String(blk.Version())) + httputil.WriteSsz(w, result, "beacon_block.ssz") } -func (s *Server) getBlockDeneb(ctx context.Context, blk interfaces.ReadOnlySignedBeaconBlock) (*structs.GetBlockV2Response, error) { - consensusBlk, err := blk.PbDenebBlock() +func (*Server) getBlockResponseBodySsz(blk interfaces.ReadOnlySignedBeaconBlock) ([]byte, error) { + err := blocks.BeaconBlockIsNil(blk) if err != nil { - // ErrUnsupportedGetter means that we have another block type - if errors.Is(err, consensus_types.ErrUnsupportedField) { - blindedConsensusBlk, err := blk.PbBlindedDenebBlock() - if err != nil { - return nil, err - } - if blindedConsensusBlk == nil { - return nil, errNilBlock - } - fullBlk, err := s.ExecutionPayloadReconstructor.ReconstructFullBlock(ctx, blk) - if err != nil { - return nil, errors.Wrapf(err, "could not reconstruct full execution payload to create signed beacon block") - } - consensusBlk, err = fullBlk.PbDenebBlock() - if err != nil { - return nil, errors.Wrapf(err, "could not get signed beacon block") - } - } else { - return nil, err - } - } - - if consensusBlk == nil { return nil, errNilBlock } - root, err := blk.Block().HashTreeRoot() - if err != nil { - return nil, errors.Wrapf(err, "could not get block root") - } - isOptimistic, err := s.OptimisticModeFetcher.IsOptimisticForRoot(ctx, root) - if err != nil { - return nil, errors.Wrapf(err, "could not check if block is optimistic") - } - respBlk, err := structs.SignedBeaconBlockDenebFromConsensus(consensusBlk) - if err != nil { - return nil, err - } - jsonBytes, err := json.Marshal(respBlk.Message) - if err != nil { - return nil, err - } - return &structs.GetBlockV2Response{ - Version: version.String(version.Deneb), - ExecutionOptimistic: isOptimistic, - Data: &structs.SignedBlock{ - Message: jsonBytes, - Signature: respBlk.Signature, - }, - }, nil -} - -func (*Server) getBlockPhase0SSZ(_ context.Context, blk interfaces.ReadOnlySignedBeaconBlock) ([]byte, error) { - consensusBlk, err := blk.PbPhase0Block() + pb, err := blk.Proto() if err != nil { return nil, err } - if consensusBlk == nil { - return nil, errNilBlock - } - sszData, err := consensusBlk.MarshalSSZ() - if err != nil { - return nil, errors.Wrapf(err, "could not marshal block into SSZ") - } - return sszData, nil -} - -func (*Server) getBlockAltairSSZ(_ context.Context, blk interfaces.ReadOnlySignedBeaconBlock) ([]byte, error) { - consensusBlk, err := blk.PbAltairBlock() - if err != nil { - return nil, err - } - if consensusBlk == nil { - return nil, errNilBlock - } - sszData, err := consensusBlk.MarshalSSZ() - if err != nil { - return nil, errors.Wrapf(err, "could not marshal block into SSZ") - } - return sszData, nil -} - -func (s *Server) getBlockBellatrixSSZ(ctx context.Context, blk interfaces.ReadOnlySignedBeaconBlock) ([]byte, error) { - consensusBlk, err := blk.PbBellatrixBlock() - if err != nil { - // ErrUnsupportedField means that we have another block type - if errors.Is(err, consensus_types.ErrUnsupportedField) { - blindedConsensusBlk, err := blk.PbBlindedBellatrixBlock() - if err != nil { - return nil, err - } - if blindedConsensusBlk == nil { - return nil, errNilBlock - } - fullBlk, err := s.ExecutionPayloadReconstructor.ReconstructFullBlock(ctx, blk) - if err != nil { - return nil, errors.Wrapf(err, "could not reconstruct full execution payload to create signed beacon block") - } - consensusBlk, err = fullBlk.PbBellatrixBlock() - if err != nil { - return nil, errors.Wrapf(err, "could not get signed beacon block") - } - } else { - return nil, err - } - } - - if consensusBlk == nil { - return nil, errNilBlock - } - sszData, err := consensusBlk.MarshalSSZ() - if err != nil { - return nil, errors.Wrapf(err, "could not marshal block into SSZ") - } - return sszData, nil -} - -func (s *Server) getBlockCapellaSSZ(ctx context.Context, blk interfaces.ReadOnlySignedBeaconBlock) ([]byte, error) { - consensusBlk, err := blk.PbCapellaBlock() - if err != nil { - // ErrUnsupportedField means that we have another block type - if errors.Is(err, consensus_types.ErrUnsupportedField) { - blindedConsensusBlk, err := blk.PbBlindedCapellaBlock() - if err != nil { - return nil, err - } - if blindedConsensusBlk == nil { - return nil, errNilBlock - } - fullBlk, err := s.ExecutionPayloadReconstructor.ReconstructFullBlock(ctx, blk) - if err != nil { - return nil, errors.Wrapf(err, "could not reconstruct full execution payload to create signed beacon block") - } - consensusBlk, err = fullBlk.PbCapellaBlock() - if err != nil { - return nil, errors.Wrapf(err, "could not get signed beacon block") - } - } else { - return nil, err - } - } - - if consensusBlk == nil { - return nil, errNilBlock + marshaler, ok := pb.(ssz.Marshaler) + if !ok { + return nil, errMarshalSSZ } - sszData, err := consensusBlk.MarshalSSZ() + sszData, err := marshaler.MarshalSSZ() if err != nil { return nil, errors.Wrapf(err, "could not marshal block into SSZ") } return sszData, nil } -func (s *Server) getBlockDenebSSZ(ctx context.Context, blk interfaces.ReadOnlySignedBeaconBlock) ([]byte, error) { - consensusBlk, err := blk.PbDenebBlock() - if err != nil { - // ErrUnsupportedGetter means that we have another block type - if errors.Is(err, consensus_types.ErrUnsupportedField) { - blindedConsensusBlk, err := blk.PbBlindedDenebBlock() - if err != nil { - return nil, err - } - if blindedConsensusBlk == nil { - return nil, errNilBlock - } - fullBlk, err := s.ExecutionPayloadReconstructor.ReconstructFullBlock(ctx, blk) - if err != nil { - return nil, errors.Wrapf(err, "could not reconstruct full execution payload to create signed beacon block") - } - consensusBlk, err = fullBlk.PbDenebBlock() - if err != nil { - return nil, errors.Wrapf(err, "could not get signed beacon block") - } - } else { - return nil, err - } - } - - if consensusBlk == nil { - return nil, errNilBlock - } - sszData, err := consensusBlk.MarshalSSZ() +// getBlockV2Json returns the JSON-serialized version of the beacon block for given block ID. +func (s *Server) getBlockV2Json(ctx context.Context, w http.ResponseWriter, blk interfaces.ReadOnlySignedBeaconBlock) { + result, err := s.getBlockResponseBodyJson(ctx, blk) if err != nil { - return nil, errors.Wrapf(err, "could not marshal block into SSZ") + httputil.HandleError(w, "Error processing request: "+err.Error(), http.StatusInternalServerError) } - return sszData, nil + w.Header().Set(api.VersionHeader, result.Version) + httputil.WriteJson(w, result) } -func (s *Server) getBlindedBlockBellatrix(ctx context.Context, blk interfaces.ReadOnlySignedBeaconBlock) (*structs.GetBlockV2Response, error) { - blindedConsensusBlk, err := blk.PbBlindedBellatrixBlock() - if err != nil { - // ErrUnsupportedField means that we have another block type - if errors.Is(err, consensus_types.ErrUnsupportedField) { - consensusBlk, err := blk.PbBellatrixBlock() - if err != nil { - return nil, err - } - if consensusBlk == nil { - return nil, errNilBlock - } - blkInterface, err := blk.ToBlinded() - if err != nil { - return nil, errors.Wrapf(err, "could not convert block to blinded block") - } - blindedConsensusBlk, err = blkInterface.PbBlindedBellatrixBlock() - if err != nil { - return nil, errors.Wrapf(err, "could not get signed beacon block") - } - } else { - return nil, err - } - } - - if blindedConsensusBlk == nil { - return nil, errNilBlock - } - root, err := blk.Block().HashTreeRoot() - if err != nil { - return nil, errors.Wrapf(err, "could not get block root") - } - isOptimistic, err := s.OptimisticModeFetcher.IsOptimisticForRoot(ctx, root) - if err != nil { - return nil, errors.Wrapf(err, "could not check if block is optimistic") - } - respBlk, err := structs.SignedBlindedBeaconBlockBellatrixFromConsensus(blindedConsensusBlk) - if err != nil { +func (s *Server) getBlockResponseBodyJson(ctx context.Context, blk interfaces.ReadOnlySignedBeaconBlock) (*structs.GetBlockV2Response, error) { + if err := blocks.BeaconBlockIsNil(blk); err != nil { return nil, err } - jsonBytes, err := json.Marshal(respBlk.Message) - if err != nil { - return nil, err - } - return &structs.GetBlockV2Response{ - Version: version.String(version.Bellatrix), - ExecutionOptimistic: isOptimistic, - Data: &structs.SignedBlock{ - Message: jsonBytes, - Signature: respBlk.Signature, - }, - }, nil -} - -func (s *Server) getBlindedBlockCapella(ctx context.Context, blk interfaces.ReadOnlySignedBeaconBlock) (*structs.GetBlockV2Response, error) { - blindedConsensusBlk, err := blk.PbBlindedCapellaBlock() - if err != nil { - // ErrUnsupportedField means that we have another block type - if errors.Is(err, consensus_types.ErrUnsupportedField) { - consensusBlk, err := blk.PbCapellaBlock() - if err != nil { - return nil, err - } - if consensusBlk == nil { - return nil, errNilBlock - } - blkInterface, err := blk.ToBlinded() - if err != nil { - return nil, errors.Wrapf(err, "could not convert block to blinded block") - } - blindedConsensusBlk, err = blkInterface.PbBlindedCapellaBlock() - if err != nil { - return nil, errors.Wrapf(err, "could not get signed beacon block") - } - } else { - return nil, err - } - } - - if blindedConsensusBlk == nil { - return nil, errNilBlock - } - root, err := blk.Block().HashTreeRoot() - if err != nil { - return nil, errors.Wrapf(err, "could not get block root") - } - isOptimistic, err := s.OptimisticModeFetcher.IsOptimisticForRoot(ctx, root) - if err != nil { - return nil, errors.Wrapf(err, "could not check if block is optimistic") - } - respBlk, err := structs.SignedBlindedBeaconBlockCapellaFromConsensus(blindedConsensusBlk) - if err != nil { - return nil, err - } - jsonBytes, err := json.Marshal(respBlk.Message) + blkRoot, err := blk.Block().HashTreeRoot() if err != nil { - return nil, err + return nil, errors.Wrap(err, "could not get block root") } - return &structs.GetBlockV2Response{ - Version: version.String(version.Capella), - ExecutionOptimistic: isOptimistic, - Data: &structs.SignedBlock{ - Message: jsonBytes, - Signature: respBlk.Signature, - }, - }, nil -} - -func (s *Server) getBlindedBlockDeneb(ctx context.Context, blk interfaces.ReadOnlySignedBeaconBlock) (*structs.GetBlockV2Response, error) { - blindedConsensusBlk, err := blk.PbBlindedDenebBlock() - if err != nil { - // ErrUnsupportedGetter means that we have another block type - if errors.Is(err, consensus_types.ErrUnsupportedField) { - consensusBlk, err := blk.PbDenebBlock() - if err != nil { - return nil, err - } - if consensusBlk == nil { - return nil, errNilBlock - } - blkInterface, err := blk.ToBlinded() - if err != nil { - return nil, errors.Wrapf(err, "could not convert block to blinded block") - } - blindedConsensusBlk, err = blkInterface.PbBlindedDenebBlock() - if err != nil { - return nil, errors.Wrapf(err, "could not get signed beacon block") - } - } else { - return nil, err + finalized := s.FinalizationFetcher.IsFinalized(ctx, blkRoot) + isOptimistic := false + if blk.Version() >= version.Bellatrix { + isOptimistic, err = s.OptimisticModeFetcher.IsOptimisticForRoot(ctx, blkRoot) + if err != nil { + return nil, errors.Wrap(err, "could not check if block is optimistic") } } - - if blindedConsensusBlk == nil { - return nil, errNilBlock - } - root, err := blk.Block().HashTreeRoot() - if err != nil { - return nil, errors.Wrapf(err, "could not get block root") - } - isOptimistic, err := s.OptimisticModeFetcher.IsOptimisticForRoot(ctx, root) - if err != nil { - return nil, errors.Wrapf(err, "could not check if block is optimistic") - } - respBlk, err := structs.SignedBlindedBeaconBlockDenebFromConsensus(blindedConsensusBlk) + mj, err := structs.SignedBeaconBlockMessageJsoner(blk) if err != nil { return nil, err } - jsonBytes, err := json.Marshal(respBlk.Message) + jb, err := mj.MessageRawJson() if err != nil { return nil, err } return &structs.GetBlockV2Response{ - Version: version.String(version.Deneb), + Finalized: finalized, ExecutionOptimistic: isOptimistic, + Version: version.String(blk.Version()), Data: &structs.SignedBlock{ - Message: jsonBytes, - Signature: respBlk.Signature, + Message: jb, + Signature: mj.SigString(), }, }, nil } -func (*Server) getBlindedBlockBellatrixSSZ(_ context.Context, blk interfaces.ReadOnlySignedBeaconBlock) ([]byte, error) { - blindedConsensusBlk, err := blk.PbBlindedBellatrixBlock() - if err != nil { - // ErrUnsupportedField means that we have another block type - if errors.Is(err, consensus_types.ErrUnsupportedField) { - consensusBlk, err := blk.PbBellatrixBlock() - if err != nil { - return nil, err - } - if consensusBlk == nil { - return nil, errNilBlock - } - blkInterface, err := blk.ToBlinded() - if err != nil { - return nil, errors.Wrapf(err, "could not convert block to blinded block") - } - blindedConsensusBlk, err = blkInterface.PbBlindedBellatrixBlock() - if err != nil { - return nil, errors.Wrapf(err, "could not get signed beacon block") - } - } else { - return nil, err - } - } - - if blindedConsensusBlk == nil { - return nil, errNilBlock - } - sszData, err := blindedConsensusBlk.MarshalSSZ() - if err != nil { - return nil, errors.Wrapf(err, "could not marshal block into SSZ") - } - return sszData, nil -} - -func (*Server) getBlindedBlockCapellaSSZ(_ context.Context, blk interfaces.ReadOnlySignedBeaconBlock) ([]byte, error) { - blindedConsensusBlk, err := blk.PbBlindedCapellaBlock() - if err != nil { - // ErrUnsupportedField means that we have another block type - if errors.Is(err, consensus_types.ErrUnsupportedField) { - consensusBlk, err := blk.PbCapellaBlock() - if err != nil { - return nil, err - } - if consensusBlk == nil { - return nil, errNilBlock - } - blkInterface, err := blk.ToBlinded() - if err != nil { - return nil, errors.Wrapf(err, "could not convert block to blinded block") - } - blindedConsensusBlk, err = blkInterface.PbBlindedCapellaBlock() - if err != nil { - return nil, errors.Wrapf(err, "could not get signed beacon block") - } - } else { - return nil, err - } - } - - if blindedConsensusBlk == nil { - return nil, errNilBlock - } - sszData, err := blindedConsensusBlk.MarshalSSZ() - if err != nil { - return nil, errors.Wrapf(err, "could not marshal block into SSZ") - } - return sszData, nil -} - -func (*Server) getBlindedBlockDenebSSZ(_ context.Context, blk interfaces.ReadOnlySignedBeaconBlock) ([]byte, error) { - blindedConsensusBlk, err := blk.PbBlindedDenebBlock() - if err != nil { - // ErrUnsupportedGetter means that we have another block type - if errors.Is(err, consensus_types.ErrUnsupportedField) { - consensusBlk, err := blk.PbDenebBlock() - if err != nil { - return nil, err - } - if consensusBlk == nil { - return nil, errNilBlock - } - blkInterface, err := blk.ToBlinded() - if err != nil { - return nil, errors.Wrapf(err, "could not convert block to blinded block") - } - blindedConsensusBlk, err = blkInterface.PbBlindedDenebBlock() - if err != nil { - return nil, errors.Wrapf(err, "could not get signed beacon block") - } - } else { - return nil, err - } - } - - if blindedConsensusBlk == nil { - return nil, errNilBlock - } - sszData, err := blindedConsensusBlk.MarshalSSZ() - if err != nil { - return nil, errors.Wrapf(err, "could not marshal block into SSZ") - } - return sszData, nil -} - // GetBlockAttestations retrieves attestation included in requested block. func (s *Server) GetBlockAttestations(w http.ResponseWriter, r *http.Request) { ctx, span := trace.StartSpan(r.Context(), "beacon.GetBlockAttestations") diff --git a/beacon-chain/rpc/lookup/blocker_test.go b/beacon-chain/rpc/lookup/blocker_test.go index 903e931db1a4..93c404ca8cc4 100644 --- a/beacon-chain/rpc/lookup/blocker_test.go +++ b/beacon-chain/rpc/lookup/blocker_test.go @@ -146,8 +146,10 @@ func TestGetBlock(t *testing.T) { return } require.NoError(t, err) - pbBlock, err := result.PbPhase0Block() + pb, err := result.Proto() require.NoError(t, err) + pbBlock, ok := pb.(*ethpbalpha.SignedBeaconBlock) + require.Equal(t, true, ok) if !reflect.DeepEqual(pbBlock, tt.want) { t.Error("Expected blocks to equal") } diff --git a/beacon-chain/rpc/prysm/v1alpha1/beacon/blocks.go b/beacon-chain/rpc/prysm/v1alpha1/beacon/blocks.go index 0c1145bca135..b6315f886698 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/beacon/blocks.go +++ b/beacon-chain/rpc/prysm/v1alpha1/beacon/blocks.go @@ -13,7 +13,6 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/time/slots" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -90,64 +89,32 @@ func convertToBlockContainer(blk interfaces.ReadOnlySignedBeaconBlock, root [32] Canonical: isCanonical, } - switch blk.Version() { - case version.Phase0: - rBlk, err := blk.PbPhase0Block() - if err != nil { - return nil, err - } - ctr.Block = ðpb.BeaconBlockContainer_Phase0Block{Phase0Block: rBlk} - case version.Altair: - rBlk, err := blk.PbAltairBlock() - if err != nil { - return nil, err - } - ctr.Block = ðpb.BeaconBlockContainer_AltairBlock{AltairBlock: rBlk} - case version.Bellatrix: - if blk.IsBlinded() { - rBlk, err := blk.PbBlindedBellatrixBlock() - if err != nil { - return nil, err - } - ctr.Block = ðpb.BeaconBlockContainer_BlindedBellatrixBlock{BlindedBellatrixBlock: rBlk} - } else { - rBlk, err := blk.PbBellatrixBlock() - if err != nil { - return nil, err - } - ctr.Block = ðpb.BeaconBlockContainer_BellatrixBlock{BellatrixBlock: rBlk} - } - case version.Capella: - if blk.IsBlinded() { - rBlk, err := blk.PbBlindedCapellaBlock() - if err != nil { - return nil, err - } - ctr.Block = ðpb.BeaconBlockContainer_BlindedCapellaBlock{BlindedCapellaBlock: rBlk} - } else { - rBlk, err := blk.PbCapellaBlock() - if err != nil { - return nil, err - } - ctr.Block = ðpb.BeaconBlockContainer_CapellaBlock{CapellaBlock: rBlk} - } - case version.Deneb: - if blk.IsBlinded() { - rBlk, err := blk.PbBlindedDenebBlock() - if err != nil { - return nil, err - } - ctr.Block = ðpb.BeaconBlockContainer_BlindedDenebBlock{BlindedDenebBlock: rBlk} - } else { - rBlk, err := blk.PbDenebBlock() - if err != nil { - return nil, err - } - ctr.Block = ðpb.BeaconBlockContainer_DenebBlock{DenebBlock: rBlk} - } + pb, err := blk.Proto() + if err != nil { + return nil, err + } + + switch pbStruct := pb.(type) { + case *ethpb.SignedBeaconBlock: + ctr.Block = ðpb.BeaconBlockContainer_Phase0Block{Phase0Block: pbStruct} + case *ethpb.SignedBeaconBlockAltair: + ctr.Block = ðpb.BeaconBlockContainer_AltairBlock{AltairBlock: pbStruct} + case *ethpb.SignedBlindedBeaconBlockBellatrix: + ctr.Block = ðpb.BeaconBlockContainer_BlindedBellatrixBlock{BlindedBellatrixBlock: pbStruct} + case *ethpb.SignedBeaconBlockBellatrix: + ctr.Block = ðpb.BeaconBlockContainer_BellatrixBlock{BellatrixBlock: pbStruct} + case *ethpb.SignedBlindedBeaconBlockCapella: + ctr.Block = ðpb.BeaconBlockContainer_BlindedCapellaBlock{BlindedCapellaBlock: pbStruct} + case *ethpb.SignedBeaconBlockCapella: + ctr.Block = ðpb.BeaconBlockContainer_CapellaBlock{CapellaBlock: pbStruct} + case *ethpb.SignedBlindedBeaconBlockDeneb: + ctr.Block = ðpb.BeaconBlockContainer_BlindedDenebBlock{BlindedDenebBlock: pbStruct} + case *ethpb.SignedBeaconBlockDeneb: + ctr.Block = ðpb.BeaconBlockContainer_DenebBlock{DenebBlock: pbStruct} default: return nil, errors.Errorf("block type is not recognized: %d", blk.Version()) } + return ctr, nil } diff --git a/beacon-chain/rpc/prysm/v1alpha1/beacon/blocks_test.go b/beacon-chain/rpc/prysm/v1alpha1/beacon/blocks_test.go index 613e8d26e7d7..fb6900d5eed1 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/beacon/blocks_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/beacon/blocks_test.go @@ -265,8 +265,10 @@ func TestServer_ListBeaconBlocks_Genesis(t *testing.T) { assert.NoError(t, err) blinded, err := wrapped.ToBlinded() assert.NoError(t, err) - blindedProto, err := blinded.PbBlindedBellatrixBlock() + pb, err := blinded.Proto() assert.NoError(t, err) + blindedProto, ok := pb.(*ethpb.SignedBlindedBeaconBlockBellatrix) + require.Equal(t, true, ok) blkContainer := ðpb.BeaconBlockContainer{ Block: ðpb.BeaconBlockContainer_BlindedBellatrixBlock{BlindedBellatrixBlock: blindedProto}} runListBlocksGenesis(t, wrapped, blkContainer) @@ -279,7 +281,10 @@ func TestServer_ListBeaconBlocks_Genesis(t *testing.T) { assert.NoError(t, err) blinded, err := wrapped.ToBlinded() assert.NoError(t, err) - blindedProto, err := blinded.PbBlindedCapellaBlock() + pb, err := blinded.Proto() + assert.NoError(t, err) + blindedProto, ok := pb.(*ethpb.SignedBlindedBeaconBlockCapella) + require.Equal(t, true, ok) assert.NoError(t, err) blkContainer := ðpb.BeaconBlockContainer{ Block: ðpb.BeaconBlockContainer_BlindedCapellaBlock{BlindedCapellaBlock: blindedProto}} diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_deneb.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_deneb.go index ca052e431ea3..589f100fd692 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_deneb.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_deneb.go @@ -61,11 +61,11 @@ func BuildBlobSidecars(blk interfaces.SignedBeaconBlock, blobs [][]byte, kzgProo if blk.Version() < version.Deneb { return nil, nil // No blobs before deneb. } - denebBlk, err := blk.PbDenebBlock() + commits, err := blk.Block().Body().BlobKzgCommitments() if err != nil { return nil, err } - cLen := len(denebBlk.Block.Body.BlobKzgCommitments) + cLen := len(commits) if cLen != len(blobs) || cLen != len(kzgProofs) { return nil, errors.New("blob KZG commitments don't match number of blobs or KZG proofs") } @@ -83,7 +83,7 @@ func BuildBlobSidecars(blk interfaces.SignedBeaconBlock, blobs [][]byte, kzgProo blobSidecars[i] = ðpb.BlobSidecar{ Index: uint64(i), Blob: blobs[i], - KzgCommitment: denebBlk.Block.Body.BlobKzgCommitments[i], + KzgCommitment: commits[i], KzgProof: kzgProofs[i], SignedBlockHeader: header, CommitmentInclusionProof: proof, diff --git a/consensus-types/blocks/execution.go b/consensus-types/blocks/execution.go index d4006244efed..9b754481b3fe 100644 --- a/consensus-types/blocks/execution.go +++ b/consensus-types/blocks/execution.go @@ -23,6 +23,23 @@ type executionPayload struct { p *enginev1.ExecutionPayload } +// NewWrappedExecutionData creates an appropriate execution payload wrapper based on the incoming type. +func NewWrappedExecutionData(v proto.Message, weiValue math.Wei) (interfaces.ExecutionData, error) { + if weiValue == nil { + weiValue = new(big.Int).SetInt64(0) + } + switch pbStruct := v.(type) { + case *enginev1.ExecutionPayload: + return WrappedExecutionPayload(pbStruct) + case *enginev1.ExecutionPayloadCapella: + return WrappedExecutionPayloadCapella(pbStruct, weiValue) + case *enginev1.ExecutionPayloadDeneb: + return WrappedExecutionPayloadDeneb(pbStruct, weiValue) + default: + return nil, ErrUnsupportedVersion + } +} + // WrappedExecutionPayload is a constructor which wraps a protobuf execution payload into an interface. func WrappedExecutionPayload(p *enginev1.ExecutionPayload) (interfaces.ExecutionData, error) { w := executionPayload{p: p} @@ -172,26 +189,6 @@ func (e executionPayload) ExcessBlobGas() (uint64, error) { return 0, consensus_types.ErrUnsupportedField } -// PbBellatrix -- -func (e executionPayload) PbBellatrix() (*enginev1.ExecutionPayload, error) { - return e.p, nil -} - -// PbCapella -- -func (executionPayload) PbCapella() (*enginev1.ExecutionPayloadCapella, error) { - return nil, consensus_types.ErrUnsupportedField -} - -// PbDeneb -- -func (executionPayload) PbDeneb() (*enginev1.ExecutionPayloadDeneb, error) { - return nil, consensus_types.ErrUnsupportedField -} - -// PbElectra -- -func (executionPayload) PbElectra() (*enginev1.ExecutionPayloadElectra, error) { - return nil, consensus_types.ErrUnsupportedField -} - // ValueInWei -- func (executionPayload) ValueInWei() (math.Wei, error) { return nil, consensus_types.ErrUnsupportedField @@ -368,26 +365,6 @@ func (e executionPayloadHeader) ExcessBlobGas() (uint64, error) { return 0, consensus_types.ErrUnsupportedField } -// PbElectra -- -func (e executionPayloadHeader) PbElectra() (*enginev1.ExecutionPayloadElectra, error) { - return nil, consensus_types.ErrUnsupportedField -} - -// PbDeneb -- -func (executionPayloadHeader) PbDeneb() (*enginev1.ExecutionPayloadDeneb, error) { - return nil, consensus_types.ErrUnsupportedField -} - -// PbCapella -- -func (executionPayloadHeader) PbCapella() (*enginev1.ExecutionPayloadCapella, error) { - return nil, consensus_types.ErrUnsupportedField -} - -// PbBellatrix -- -func (executionPayloadHeader) PbBellatrix() (*enginev1.ExecutionPayload, error) { - return nil, consensus_types.ErrUnsupportedField -} - // ValueInWei -- func (executionPayloadHeader) ValueInWei() (math.Wei, error) { return nil, consensus_types.ErrUnsupportedField @@ -594,26 +571,6 @@ func (e executionPayloadCapella) ExcessBlobGas() (uint64, error) { return 0, consensus_types.ErrUnsupportedField } -// PbElectra -- -func (executionPayloadCapella) PbElectra() (*enginev1.ExecutionPayloadElectra, error) { - return nil, consensus_types.ErrUnsupportedField -} - -// PbDeneb -- -func (executionPayloadCapella) PbDeneb() (*enginev1.ExecutionPayloadDeneb, error) { - return nil, consensus_types.ErrUnsupportedField -} - -// PbCapella -- -func (e executionPayloadCapella) PbCapella() (*enginev1.ExecutionPayloadCapella, error) { - return e.p, nil -} - -// PbBellatrix -- -func (executionPayloadCapella) PbBellatrix() (*enginev1.ExecutionPayload, error) { - return nil, consensus_types.ErrUnsupportedField -} - // ValueInWei -- func (e executionPayloadCapella) ValueInWei() (math.Wei, error) { return e.weiValue, nil @@ -792,26 +749,6 @@ func (e executionPayloadHeaderCapella) ExcessBlobGas() (uint64, error) { return 0, consensus_types.ErrUnsupportedField } -// PbElectra -- -func (executionPayloadHeaderCapella) PbElectra() (*enginev1.ExecutionPayloadElectra, error) { - return nil, consensus_types.ErrUnsupportedField -} - -// PbDeneb -- -func (executionPayloadHeaderCapella) PbDeneb() (*enginev1.ExecutionPayloadDeneb, error) { - return nil, consensus_types.ErrUnsupportedField -} - -// PbCapella -- -func (executionPayloadHeaderCapella) PbCapella() (*enginev1.ExecutionPayloadCapella, error) { - return nil, consensus_types.ErrUnsupportedField -} - -// PbBellatrix -- -func (executionPayloadHeaderCapella) PbBellatrix() (*enginev1.ExecutionPayload, error) { - return nil, consensus_types.ErrUnsupportedField -} - // ValueInWei -- func (e executionPayloadHeaderCapella) ValueInWei() (math.Wei, error) { return e.weiValue, nil @@ -1221,26 +1158,6 @@ func (e executionPayloadHeaderDeneb) ExcessBlobGas() (uint64, error) { return e.p.ExcessBlobGas, nil } -// PbElectra -- -func (executionPayloadHeaderDeneb) PbElectra() (*enginev1.ExecutionPayloadElectra, error) { - return nil, consensus_types.ErrUnsupportedField -} - -// PbDeneb -- -func (executionPayloadHeaderDeneb) PbDeneb() (*enginev1.ExecutionPayloadDeneb, error) { - return nil, consensus_types.ErrUnsupportedField -} - -// PbBellatrix -- -func (executionPayloadHeaderDeneb) PbBellatrix() (*enginev1.ExecutionPayload, error) { - return nil, consensus_types.ErrUnsupportedField -} - -// PbCapella -- -func (executionPayloadHeaderDeneb) PbCapella() (*enginev1.ExecutionPayloadCapella, error) { - return nil, consensus_types.ErrUnsupportedField -} - // ValueInWei -- func (e executionPayloadHeaderDeneb) ValueInWei() (math.Wei, error) { return e.weiValue, nil @@ -1417,26 +1334,6 @@ func (e executionPayloadDeneb) ExcessBlobGas() (uint64, error) { return e.p.ExcessBlobGas, nil } -// PbBellatrix -- -func (e executionPayloadDeneb) PbBellatrix() (*enginev1.ExecutionPayload, error) { - return nil, consensus_types.ErrUnsupportedField -} - -// PbCapella -- -func (e executionPayloadDeneb) PbCapella() (*enginev1.ExecutionPayloadCapella, error) { - return nil, consensus_types.ErrUnsupportedField -} - -// PbDeneb -- -func (e executionPayloadDeneb) PbDeneb() (*enginev1.ExecutionPayloadDeneb, error) { - return e.p, nil -} - -// PbElectra -- -func (e executionPayloadDeneb) PbElectra() (*enginev1.ExecutionPayloadElectra, error) { - return nil, consensus_types.ErrUnsupportedField -} - // ValueInWei -- func (e executionPayloadDeneb) ValueInWei() (math.Wei, error) { return e.weiValue, nil diff --git a/consensus-types/blocks/execution_test.go b/consensus-types/blocks/execution_test.go index edcb1c512dd6..f9dc7cc5e75e 100644 --- a/consensus-types/blocks/execution_test.go +++ b/consensus-types/blocks/execution_test.go @@ -211,44 +211,6 @@ func TestWrapExecutionPayloadHeaderCapella_SSZ(t *testing.T) { assert.NoError(t, payload.UnmarshalSSZ(encoded)) } -func Test_executionPayload_Pb(t *testing.T) { - payload := createWrappedPayload(t) - pb, err := payload.PbBellatrix() - require.NoError(t, err) - assert.DeepEqual(t, payload.Proto(), pb) - - _, err = payload.PbCapella() - require.ErrorIs(t, err, consensus_types.ErrUnsupportedField) -} - -func Test_executionPayloadHeader_Pb(t *testing.T) { - payload := createWrappedPayloadHeader(t) - _, err := payload.PbBellatrix() - require.ErrorIs(t, err, consensus_types.ErrUnsupportedField) - - _, err = payload.PbCapella() - require.ErrorIs(t, err, consensus_types.ErrUnsupportedField) -} - -func Test_executionPayloadCapella_Pb(t *testing.T) { - payload := createWrappedPayloadCapella(t) - pb, err := payload.PbCapella() - require.NoError(t, err) - assert.DeepEqual(t, payload.Proto(), pb) - - _, err = payload.PbBellatrix() - require.ErrorIs(t, err, consensus_types.ErrUnsupportedField) -} - -func Test_executionPayloadHeaderCapella_Pb(t *testing.T) { - payload := createWrappedPayloadHeaderCapella(t) - _, err := payload.PbBellatrix() - require.ErrorIs(t, err, consensus_types.ErrUnsupportedField) - - _, err = payload.PbCapella() - require.ErrorIs(t, err, consensus_types.ErrUnsupportedField) -} - func TestWrapExecutionPayloadDeneb(t *testing.T) { data := &enginev1.ExecutionPayloadDeneb{ ParentHash: []byte("parenthash"), diff --git a/consensus-types/blocks/getters.go b/consensus-types/blocks/getters.go index 4cc0f2c20398..2f737e80dbd0 100644 --- a/consensus-types/blocks/getters.go +++ b/consensus-types/blocks/getters.go @@ -150,102 +150,6 @@ func (b *SignedBeaconBlock) PbGenericBlock() (*eth.GenericSignedBeaconBlock, err } } -// PbPhase0Block returns the underlying protobuf object. -func (b *SignedBeaconBlock) PbPhase0Block() (*eth.SignedBeaconBlock, error) { - if b.version != version.Phase0 { - return nil, consensus_types.ErrNotSupported("PbPhase0Block", b.version) - } - pb, err := b.Proto() - if err != nil { - return nil, err - } - return pb.(*eth.SignedBeaconBlock), nil -} - -// PbAltairBlock returns the underlying protobuf object. -func (b *SignedBeaconBlock) PbAltairBlock() (*eth.SignedBeaconBlockAltair, error) { - if b.version != version.Altair { - return nil, consensus_types.ErrNotSupported("PbAltairBlock", b.version) - } - pb, err := b.Proto() - if err != nil { - return nil, err - } - return pb.(*eth.SignedBeaconBlockAltair), nil -} - -// PbBellatrixBlock returns the underlying protobuf object. -func (b *SignedBeaconBlock) PbBellatrixBlock() (*eth.SignedBeaconBlockBellatrix, error) { - if b.version != version.Bellatrix || b.IsBlinded() { - return nil, consensus_types.ErrNotSupported("PbBellatrixBlock", b.version) - } - pb, err := b.Proto() - if err != nil { - return nil, err - } - return pb.(*eth.SignedBeaconBlockBellatrix), nil -} - -// PbBlindedBellatrixBlock returns the underlying protobuf object. -func (b *SignedBeaconBlock) PbBlindedBellatrixBlock() (*eth.SignedBlindedBeaconBlockBellatrix, error) { - if b.version != version.Bellatrix || !b.IsBlinded() { - return nil, consensus_types.ErrNotSupported("PbBlindedBellatrixBlock", b.version) - } - pb, err := b.Proto() - if err != nil { - return nil, err - } - return pb.(*eth.SignedBlindedBeaconBlockBellatrix), nil -} - -// PbCapellaBlock returns the underlying protobuf object. -func (b *SignedBeaconBlock) PbCapellaBlock() (*eth.SignedBeaconBlockCapella, error) { - if b.version != version.Capella || b.IsBlinded() { - return nil, consensus_types.ErrNotSupported("PbCapellaBlock", b.version) - } - pb, err := b.Proto() - if err != nil { - return nil, err - } - return pb.(*eth.SignedBeaconBlockCapella), nil -} - -// PbBlindedCapellaBlock returns the underlying protobuf object. -func (b *SignedBeaconBlock) PbBlindedCapellaBlock() (*eth.SignedBlindedBeaconBlockCapella, error) { - if b.version != version.Capella || !b.IsBlinded() { - return nil, consensus_types.ErrNotSupported("PbBlindedCapellaBlock", b.version) - } - pb, err := b.Proto() - if err != nil { - return nil, err - } - return pb.(*eth.SignedBlindedBeaconBlockCapella), nil -} - -// PbDenebBlock returns the underlying protobuf object. -func (b *SignedBeaconBlock) PbDenebBlock() (*eth.SignedBeaconBlockDeneb, error) { - if b.version != version.Deneb || b.IsBlinded() { - return nil, consensus_types.ErrNotSupported("PbDenebBlock", b.version) - } - pb, err := b.Proto() - if err != nil { - return nil, err - } - return pb.(*eth.SignedBeaconBlockDeneb), nil -} - -// PbBlindedDenebBlock returns the underlying protobuf object. -func (b *SignedBeaconBlock) PbBlindedDenebBlock() (*eth.SignedBlindedBeaconBlockDeneb, error) { - if b.version != version.Deneb || !b.IsBlinded() { - return nil, consensus_types.ErrNotSupported("PbBlindedDenebBlock", b.version) - } - pb, err := b.Proto() - if err != nil { - return nil, err - } - return pb.(*eth.SignedBlindedBeaconBlockDeneb), nil -} - // ToBlinded converts a non-blinded block to its blinded equivalent. func (b *SignedBeaconBlock) ToBlinded() (interfaces.ReadOnlySignedBeaconBlock, error) { if b.version < version.Bellatrix { diff --git a/consensus-types/blocks/testing/BUILD.bazel b/consensus-types/blocks/testing/BUILD.bazel index e9ef642c4a39..32cb182180b0 100644 --- a/consensus-types/blocks/testing/BUILD.bazel +++ b/consensus-types/blocks/testing/BUILD.bazel @@ -14,7 +14,6 @@ go_library( "//consensus-types/interfaces:go_default_library", "//consensus-types/primitives:go_default_library", "//proto/prysm/v1alpha1:go_default_library", - "//runtime/version:go_default_library", "@com_github_pkg_errors//:go_default_library", ], ) diff --git a/consensus-types/blocks/testing/mutator.go b/consensus-types/blocks/testing/mutator.go index 9a7be2bb881e..23178b31510b 100644 --- a/consensus-types/blocks/testing/mutator.go +++ b/consensus-types/blocks/testing/mutator.go @@ -5,7 +5,6 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/runtime/version" ) type blockMutator struct { @@ -16,38 +15,23 @@ type blockMutator struct { } func (m blockMutator) apply(b interfaces.SignedBeaconBlock) (interfaces.SignedBeaconBlock, error) { - switch b.Version() { - case version.Phase0: - bb, err := b.PbPhase0Block() - if err != nil { - return nil, err - } - m.Phase0(bb) - return blocks.NewSignedBeaconBlock(bb) - case version.Altair: - bb, err := b.PbAltairBlock() - if err != nil { - return nil, err - } - m.Altair(bb) - return blocks.NewSignedBeaconBlock(bb) - case version.Bellatrix: - bb, err := b.PbBellatrixBlock() - if err != nil { - return nil, err - } - m.Bellatrix(bb) - return blocks.NewSignedBeaconBlock(bb) - case version.Capella: - bb, err := b.PbCapellaBlock() - if err != nil { - return nil, err - } - m.Capella(bb) - return blocks.NewSignedBeaconBlock(bb) + pb, err := b.Proto() + if err != nil { + return nil, err + } + switch pbStruct := pb.(type) { + case *eth.SignedBeaconBlock: + m.Phase0(pbStruct) + case *eth.SignedBeaconBlockAltair: + m.Altair(pbStruct) + case *eth.SignedBeaconBlockBellatrix: + m.Bellatrix(pbStruct) + case *eth.SignedBeaconBlockCapella: + m.Capella(pbStruct) default: return nil, blocks.ErrUnsupportedSignedBeaconBlock } + return blocks.NewSignedBeaconBlock(pb) } // SetBlockStateRoot modifies the block's state root. diff --git a/consensus-types/interfaces/beacon_block.go b/consensus-types/interfaces/beacon_block.go index 08cc1ef88d01..06d427b62805 100644 --- a/consensus-types/interfaces/beacon_block.go +++ b/consensus-types/interfaces/beacon_block.go @@ -21,15 +21,7 @@ type ReadOnlySignedBeaconBlock interface { Copy() (SignedBeaconBlock, error) Proto() (proto.Message, error) PbGenericBlock() (*ethpb.GenericSignedBeaconBlock, error) - PbPhase0Block() (*ethpb.SignedBeaconBlock, error) - PbAltairBlock() (*ethpb.SignedBeaconBlockAltair, error) ToBlinded() (ReadOnlySignedBeaconBlock, error) - PbBellatrixBlock() (*ethpb.SignedBeaconBlockBellatrix, error) - PbBlindedBellatrixBlock() (*ethpb.SignedBlindedBeaconBlockBellatrix, error) - PbCapellaBlock() (*ethpb.SignedBeaconBlockCapella, error) - PbDenebBlock() (*ethpb.SignedBeaconBlockDeneb, error) - PbBlindedCapellaBlock() (*ethpb.SignedBlindedBeaconBlockCapella, error) - PbBlindedDenebBlock() (*ethpb.SignedBlindedBeaconBlockDeneb, error) ssz.Marshaler ssz.Unmarshaler Version() int @@ -131,10 +123,6 @@ type ExecutionData interface { TransactionsRoot() ([]byte, error) Withdrawals() ([]*enginev1.Withdrawal, error) WithdrawalsRoot() ([]byte, error) - PbCapella() (*enginev1.ExecutionPayloadCapella, error) - PbBellatrix() (*enginev1.ExecutionPayload, error) - PbDeneb() (*enginev1.ExecutionPayloadDeneb, error) - PbElectra() (*enginev1.ExecutionPayloadElectra, error) ValueInWei() (math.Wei, error) ValueInGwei() (uint64, error) DepositReceipts() ([]*enginev1.DepositReceipt, error) diff --git a/consensus-types/mock/block.go b/consensus-types/mock/block.go index 452c8720d55f..6c9909e595e8 100644 --- a/consensus-types/mock/block.go +++ b/consensus-types/mock/block.go @@ -43,38 +43,6 @@ func (SignedBeaconBlock) Proto() (proto.Message, error) { panic("implement me") } -func (SignedBeaconBlock) PbPhase0Block() (*eth.SignedBeaconBlock, error) { - panic("implement me") -} - -func (SignedBeaconBlock) PbAltairBlock() (*eth.SignedBeaconBlockAltair, error) { - panic("implement me") -} - -func (SignedBeaconBlock) PbBellatrixBlock() (*eth.SignedBeaconBlockBellatrix, error) { - panic("implement me") -} - -func (SignedBeaconBlock) PbBlindedBellatrixBlock() (*eth.SignedBlindedBeaconBlockBellatrix, error) { - panic("implement me") -} - -func (SignedBeaconBlock) PbCapellaBlock() (*eth.SignedBeaconBlockCapella, error) { - panic("implement me") -} - -func (SignedBeaconBlock) PbBlindedCapellaBlock() (*eth.SignedBlindedBeaconBlockCapella, error) { - panic("implement me") -} - -func (SignedBeaconBlock) PbDenebBlock() (*eth.SignedBeaconBlockDeneb, error) { - panic("implement me") -} - -func (SignedBeaconBlock) PbBlindedDenebBlock() (*eth.SignedBlindedBeaconBlockDeneb, error) { - panic("implement me") -} - func (SignedBeaconBlock) MarshalSSZTo(_ []byte) ([]byte, error) { panic("implement me") } diff --git a/testing/middleware/builder/builder.go b/testing/middleware/builder/builder.go index 88ce400bce90..1543dd47e905 100644 --- a/testing/middleware/builder/builder.go +++ b/testing/middleware/builder/builder.go @@ -7,7 +7,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "math/big" "net" "net/http" @@ -152,7 +151,7 @@ func New(opts ...Option) (*Builder, error) { router.HandleFunc(registerPath, p.registerValidators) router.HandleFunc(headerPath, p.handleHeaderRequest) router.HandleFunc(blindedPath, p.handleBlindedBlock) - addr := fmt.Sprintf("%s:%d", p.cfg.builderHost, p.cfg.builderPort) + addr := net.JoinHostPort(p.cfg.builderHost, strconv.Itoa(p.cfg.builderPort)) srv := &http.Server{ Handler: mux, Addr: addr, @@ -268,7 +267,7 @@ func (p *Builder) handleEngineCalls(req, resp []byte) { } payloadID := [8]byte{} status := "" - lastValHash := []byte{} + var lastValHash []byte if result.Result.PayloadId != nil { payloadID = *result.Result.PayloadId } @@ -280,7 +279,7 @@ func (p *Builder) handleEngineCalls(req, resp []byte) { } } -func (p *Builder) isBuilderCall(req *http.Request) bool { +func (*Builder) isBuilderCall(req *http.Request) bool { return strings.Contains(req.URL.Path, "/eth/v1/builder/") } @@ -523,7 +522,7 @@ func (p *Builder) handleHeaderRequestDeneb(w http.ResponseWriter) { return } val := builderAPI.Uint256{Int: v} - commitments := []hexutil.Bytes{} + var commitments []hexutil.Bytes for _, c := range b.BlobsBundle.KzgCommitments { copiedC := c commitments = append(commitments, copiedC) @@ -592,66 +591,14 @@ func (p *Builder) handleBlindedBlock(w http.ResponseWriter, req *http.Request) { http.Error(w, "payload not found", http.StatusInternalServerError) return } - if payload, err := p.currPayload.PbDeneb(); err == nil { - convertedPayload, err := builderAPI.FromProtoDeneb(payload) - if err != nil { - p.cfg.logger.WithError(err).Error("Could not convert the payload") - http.Error(w, "payload not found", http.StatusInternalServerError) - return - } - execResp := &builderAPI.ExecPayloadResponseDeneb{ - Version: "deneb", - Data: &builderAPI.ExecutionPayloadDenebAndBlobsBundle{ - ExecutionPayload: &convertedPayload, - BlobsBundle: builderAPI.FromBundleProto(p.blobBundle), - }, - } - err = json.NewEncoder(w).Encode(execResp) - if err != nil { - p.cfg.logger.WithError(err).Error("Could not encode full payload response") - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - w.WriteHeader(http.StatusOK) - return - } - if payload, err := p.currPayload.PbCapella(); err == nil { - convertedPayload, err := builderAPI.FromProtoCapella(payload) - if err != nil { - p.cfg.logger.WithError(err).Error("Could not convert the payload") - http.Error(w, "payload not found", http.StatusInternalServerError) - return - } - execResp := &builderAPI.ExecPayloadResponseCapella{ - Version: "capella", - Data: convertedPayload, - } - err = json.NewEncoder(w).Encode(execResp) - if err != nil { - p.cfg.logger.WithError(err).Error("Could not encode full payload response") - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - w.WriteHeader(http.StatusOK) - return - } - bellPayload, err := p.currPayload.PbBellatrix() - if err != nil { - p.cfg.logger.WithError(err).Error("Could not retrieve the payload") - http.Error(w, "payload not found", http.StatusInternalServerError) - return - } - convertedPayload, err := builderAPI.FromProto(bellPayload) + + resp, err := builderAPI.ExecutionPayloadResponseFromData(p.currPayload, p.blobBundle) if err != nil { p.cfg.logger.WithError(err).Error("Could not convert the payload") - http.Error(w, "payload not found", http.StatusInternalServerError) + http.Error(w, err.Error(), http.StatusInternalServerError) return } - execResp := &builderAPI.ExecPayloadResponse{ - Version: "bellatrix", - Data: convertedPayload, - } - err = json.NewEncoder(w).Encode(execResp) + err = json.NewEncoder(w).Encode(resp) if err != nil { p.cfg.logger.WithError(err).Error("Could not encode full payload response") http.Error(w, err.Error(), http.StatusInternalServerError) @@ -747,7 +694,7 @@ func (p *Builder) sendHttpRequest(req *http.Request, requestBytes []byte) (*http } // Set the modified request as the proxy request body. - proxyReq.Body = ioutil.NopCloser(bytes.NewBuffer(requestBytes)) + proxyReq.Body = io.NopCloser(bytes.NewBuffer(requestBytes)) // Required proxy headers for forwarding JSON-RPC requests to the execution client. proxyReq.Header.Set("Host", req.Host) @@ -768,14 +715,14 @@ func (p *Builder) sendHttpRequest(req *http.Request, requestBytes []byte) (*http // Peek into the bytes of an HTTP request's body. func parseRequestBytes(req *http.Request) ([]byte, error) { - requestBytes, err := ioutil.ReadAll(req.Body) + requestBytes, err := io.ReadAll(req.Body) if err != nil { return nil, err } if err = req.Body.Close(); err != nil { return nil, err } - req.Body = ioutil.NopCloser(bytes.NewBuffer(requestBytes)) + req.Body = io.NopCloser(bytes.NewBuffer(requestBytes)) return requestBytes, nil } diff --git a/validator/client/propose.go b/validator/client/propose.go index 12779137f0ad..986f1e66f1fe 100644 --- a/validator/client/propose.go +++ b/validator/client/propose.go @@ -128,11 +128,16 @@ func (v *validator) ProposeBlock(ctx context.Context, slot primitives.Slot, pubK var genericSignedBlock *ethpb.GenericSignedBeaconBlock if blk.Version() >= version.Deneb && !blk.IsBlinded() { - denebBlock, err := blk.PbDenebBlock() + pb, err := blk.Proto() if err != nil { log.WithError(err).Error("Failed to get deneb block") return } + denebBlock, ok := pb.(*ethpb.SignedBeaconBlockDeneb) + if !ok { + log.WithError(err).Error("Failed to get deneb block - assertion failure") + return + } genericSignedBlock = ðpb.GenericSignedBeaconBlock{ Block: ðpb.GenericSignedBeaconBlock_Deneb{ Deneb: ðpb.SignedBeaconBlockContentsDeneb{