From a41c01cb5edfb21bd53ef43cc0b3ae119dea45af Mon Sep 17 00:00:00 2001 From: james-prysm <90280386+james-prysm@users.noreply.github.com> Date: Mon, 10 Jul 2023 14:02:44 -0500 Subject: [PATCH] migrating get blob from eip4844 and deneb-integration (#12603) --- beacon-chain/blockchain/execution_engine.go | 22 +- beacon-chain/db/kv/blob.go | 6 - beacon-chain/db/kv/blob_test.go | 10 - beacon-chain/execution/engine_client.go | 5 + beacon-chain/p2p/fork_watcher.go | 3 +- beacon-chain/p2p/gossip_topic_mappings.go | 3 + beacon-chain/p2p/types/object_mapping.go | 8 + beacon-chain/rpc/BUILD.bazel | 1 + beacon-chain/rpc/apimiddleware/BUILD.bazel | 1 + .../rpc/apimiddleware/custom_handlers.go | 45 +-- .../rpc/apimiddleware/custom_handlers_test.go | 90 ------ beacon-chain/rpc/eth/blob/BUILD.bazel | 47 +++ beacon-chain/rpc/eth/blob/handlers.go | 213 ++++++++++++ beacon-chain/rpc/eth/blob/handlers_test.go | 303 ++++++++++++++++++ beacon-chain/rpc/eth/blob/server.go | 11 + beacon-chain/rpc/eth/blob/structs.go | 16 + beacon-chain/rpc/eth/helpers/BUILD.bazel | 2 + beacon-chain/rpc/eth/helpers/http.go | 17 + beacon-chain/rpc/eth/helpers/http_test.go | 21 ++ beacon-chain/rpc/service.go | 7 + beacon-chain/sync/rpc.go | 7 +- beacon-chain/sync/rpc_chunked_response.go | 6 + beacon-chain/sync/subscriber.go | 6 +- config/params/loader_test.go | 5 +- consensus-types/blocks/factory.go | 4 + consensus-types/payload-attribute/getters.go | 2 +- proto/engine/v1/json_marshal_unmarshal.go | 15 +- proto/eth/v2/BUILD.bazel | 2 + proto/eth/v2/blobs.pb.go | 168 +++++----- proto/eth/v2/blobs.proto | 2 +- proto/eth/v2/generated.ssz.go | 290 ++++++++++++++++- proto/migration/v1alpha1_to_v2.go | 19 +- proto/migration/v1alpha1_to_v2_test.go | 11 + runtime/interop/genesis.go | 2 + testing/endtoend/components/beacon_node.go | 2 +- testing/endtoend/endtoend_setup_test.go | 8 +- testing/endtoend/evaluators/fork.go | 49 +++ testing/endtoend/evaluators/operations.go | 8 + testing/endtoend/evaluators/validator.go | 6 + testing/endtoend/helpers/helpers.go | 1 + testing/util/blob.go | 21 ++ 41 files changed, 1211 insertions(+), 254 deletions(-) create mode 100644 beacon-chain/rpc/eth/blob/BUILD.bazel create mode 100644 beacon-chain/rpc/eth/blob/handlers.go create mode 100644 beacon-chain/rpc/eth/blob/handlers_test.go create mode 100644 beacon-chain/rpc/eth/blob/server.go create mode 100644 beacon-chain/rpc/eth/blob/structs.go create mode 100644 beacon-chain/rpc/eth/helpers/http.go create mode 100644 beacon-chain/rpc/eth/helpers/http_test.go diff --git a/beacon-chain/blockchain/execution_engine.go b/beacon-chain/blockchain/execution_engine.go index 4931d63b46..739d5146b5 100644 --- a/beacon-chain/blockchain/execution_engine.go +++ b/beacon-chain/blockchain/execution_engine.go @@ -2,6 +2,7 @@ package blockchain import ( "context" + "crypto/sha256" "fmt" "github.com/pkg/errors" @@ -213,12 +214,16 @@ func (s *Service) notifyNewPayload(ctx context.Context, preStateVersion int, var lastValidHash []byte if blk.Version() >= version.Deneb { - _, err = blk.Block().Body().BlobKzgCommitments() + var kzgs [][]byte + kzgs, err = blk.Block().Body().BlobKzgCommitments() if err != nil { return false, errors.Wrap(invalidBlock{error: err}, "could not get blob kzg commitments") } - // TODO: Convert kzg commitment to version hashes and feed to below - lastValidHash, err = s.cfg.ExecutionEngineCaller.NewPayload(ctx, payload, [][32]byte{}) + versionedHashes := make([][32]byte, len(kzgs)) + for i := range versionedHashes { + versionedHashes[i] = kzgToVersionedHash(kzgs[i]) + } + lastValidHash, err = s.cfg.ExecutionEngineCaller.NewPayload(ctx, payload, versionedHashes) } else { lastValidHash, err = s.cfg.ExecutionEngineCaller.NewPayload(ctx, payload, [][32]byte{} /*empty version hashes before Deneb*/) } @@ -371,3 +376,14 @@ func (s *Service) removeInvalidBlockAndState(ctx context.Context, blkRoots [][32 } return nil } + +const ( + blobCommitmentVersionKZG uint8 = 0x01 +) + +// kzgToVersionedHash implements kzg_to_versioned_hash from EIP-4844 +func kzgToVersionedHash(kzg []byte) (h [32]byte) { + h = sha256.Sum256(kzg) + h[0] = blobCommitmentVersionKZG + return +} diff --git a/beacon-chain/db/kv/blob.go b/beacon-chain/db/kv/blob.go index f3e20925ca..dec41a532d 100644 --- a/beacon-chain/db/kv/blob.go +++ b/beacon-chain/db/kv/blob.go @@ -33,7 +33,6 @@ func (s *Store) SaveBlobSidecar(ctx context.Context, scs []*ethpb.BlobSidecar) e return err } - slot := scs[0].Slot return s.db.Update(func(tx *bolt.Tx) error { encodedBlobSidecar, err := encode(ctx, ðpb.BlobSidecars{Sidecars: scs}) if err != nil { @@ -47,11 +46,6 @@ func (s *Store) SaveBlobSidecar(ctx context.Context, scs []*ethpb.BlobSidecar) e for k, _ := c.Seek(rotatingBufferPrefix); bytes.HasPrefix(k, rotatingBufferPrefix); k, _ = c.Next() { if len(k) != 0 { replacingKey = k - oldSlotBytes := replacingKey[8:16] - oldSlot := bytesutil.BytesToSlotBigEndian(oldSlotBytes) - if oldSlot >= slot { - return fmt.Errorf("attempted to save blob with slot %d but already have older blob with slot %d", slot, oldSlot) - } break } } diff --git a/beacon-chain/db/kv/blob_test.go b/beacon-chain/db/kv/blob_test.go index f08a604724..66a9fa311b 100644 --- a/beacon-chain/db/kv/blob_test.go +++ b/beacon-chain/db/kv/blob_test.go @@ -157,16 +157,6 @@ func TestStore_BlobSidecars(t *testing.T) { require.ErrorIs(t, ErrNotFound, err) require.Equal(t, 0, len(got)) }) - t.Run("saving a blob with older slot", func(t *testing.T) { - db := setupDB(t) - scs := generateBlobSidecars(t, fieldparams.MaxBlobsPerBlock) - require.NoError(t, db.SaveBlobSidecar(ctx, scs)) - require.Equal(t, int(fieldparams.MaxBlobsPerBlock), len(scs)) - got, err := db.BlobSidecarsByRoot(ctx, bytesutil.ToBytes32(scs[0].BlockRoot)) - require.NoError(t, err) - require.NoError(t, equalBlobSlices(scs, got)) - require.ErrorContains(t, "but already have older blob with slot", db.SaveBlobSidecar(ctx, scs)) - }) t.Run("saving a new blob for rotation", func(t *testing.T) { db := setupDB(t) scs := generateBlobSidecars(t, fieldparams.MaxBlobsPerBlock) diff --git a/beacon-chain/execution/engine_client.go b/beacon-chain/execution/engine_client.go index 6f719aaf52..5d299c37e1 100644 --- a/beacon-chain/execution/engine_client.go +++ b/beacon-chain/execution/engine_client.go @@ -806,6 +806,10 @@ func fullPayloadFromExecutionBlock( if err != nil { return nil, errors.Wrap(err, "unable to extract ExcessDataGas attribute from excution payload header") } + dgu, err := header.DataGasUsed() + if err != nil { + return nil, errors.Wrap(err, "unable to extract DataGasUsed attribute from excution payload header") + } return blocks.WrappedExecutionPayloadDeneb( &pb.ExecutionPayloadDeneb{ ParentHash: header.ParentHash(), @@ -824,6 +828,7 @@ func fullPayloadFromExecutionBlock( Transactions: txs, Withdrawals: block.Withdrawals, ExcessDataGas: edg, + DataGasUsed: dgu, }, 0) // We can't get the block value and don't care about the block value for this instance default: return nil, fmt.Errorf("unknown execution block version %d", block.Version) diff --git a/beacon-chain/p2p/fork_watcher.go b/beacon-chain/p2p/fork_watcher.go index 16148a0c4f..87c421e3a1 100644 --- a/beacon-chain/p2p/fork_watcher.go +++ b/beacon-chain/p2p/fork_watcher.go @@ -17,7 +17,8 @@ func (s *Service) forkWatcher() { currEpoch := slots.ToEpoch(currSlot) if currEpoch == params.BeaconConfig().AltairForkEpoch || currEpoch == params.BeaconConfig().BellatrixForkEpoch || - currEpoch == params.BeaconConfig().CapellaForkEpoch { + currEpoch == params.BeaconConfig().CapellaForkEpoch || + currEpoch == params.BeaconConfig().DenebForkEpoch { // If we are in the fork epoch, we update our enr with // the updated fork digest. These repeatedly does // this over the epoch, which might be slightly wasteful diff --git a/beacon-chain/p2p/gossip_topic_mappings.go b/beacon-chain/p2p/gossip_topic_mappings.go index 51f891294c..da941f3df8 100644 --- a/beacon-chain/p2p/gossip_topic_mappings.go +++ b/beacon-chain/p2p/gossip_topic_mappings.go @@ -28,6 +28,9 @@ var gossipTopicMappings = map[string]proto.Message{ // versioned by epoch. func GossipTopicMappings(topic string, epoch primitives.Epoch) proto.Message { if topic == BlockSubnetTopicFormat { + if epoch >= params.BeaconConfig().DenebForkEpoch { + return ðpb.SignedBeaconBlockDeneb{} + } if epoch >= params.BeaconConfig().CapellaForkEpoch { return ðpb.SignedBeaconBlockCapella{} } diff --git a/beacon-chain/p2p/types/object_mapping.go b/beacon-chain/p2p/types/object_mapping.go index f866a00057..6bfc49bd35 100644 --- a/beacon-chain/p2p/types/object_mapping.go +++ b/beacon-chain/p2p/types/object_mapping.go @@ -53,6 +53,11 @@ func InitializeDataMaps() { ðpb.SignedBeaconBlockCapella{Block: ðpb.BeaconBlockCapella{Body: ðpb.BeaconBlockBodyCapella{}}}, ) }, + bytesutil.ToBytes4(params.BeaconConfig().DenebForkVersion): func() (interfaces.ReadOnlySignedBeaconBlock, error) { + return blocks.NewSignedBeaconBlock( + ðpb.SignedBeaconBlockDeneb{Block: ðpb.BeaconBlockDeneb{Body: ðpb.BeaconBlockBodyDeneb{}}}, + ) + }, } // Reset our metadata map. @@ -69,5 +74,8 @@ func InitializeDataMaps() { bytesutil.ToBytes4(params.BeaconConfig().CapellaForkVersion): func() metadata.Metadata { return wrapper.WrappedMetadataV1(ðpb.MetaDataV1{}) }, + bytesutil.ToBytes4(params.BeaconConfig().DenebForkVersion): func() metadata.Metadata { + return wrapper.WrappedMetadataV1(ðpb.MetaDataV1{}) + }, } } diff --git a/beacon-chain/rpc/BUILD.bazel b/beacon-chain/rpc/BUILD.bazel index cc056de83d..5692d9949a 100644 --- a/beacon-chain/rpc/BUILD.bazel +++ b/beacon-chain/rpc/BUILD.bazel @@ -26,6 +26,7 @@ go_library( "//beacon-chain/p2p:go_default_library", "//beacon-chain/rpc/core:go_default_library", "//beacon-chain/rpc/eth/beacon:go_default_library", + "//beacon-chain/rpc/eth/blob:go_default_library", "//beacon-chain/rpc/eth/builder:go_default_library", "//beacon-chain/rpc/eth/debug:go_default_library", "//beacon-chain/rpc/eth/events:go_default_library", diff --git a/beacon-chain/rpc/apimiddleware/BUILD.bazel b/beacon-chain/rpc/apimiddleware/BUILD.bazel index d9710bb1ff..1b4e0d1a97 100644 --- a/beacon-chain/rpc/apimiddleware/BUILD.bazel +++ b/beacon-chain/rpc/apimiddleware/BUILD.bazel @@ -19,6 +19,7 @@ go_library( "//beacon-chain/rpc/eth/shared:go_default_library", "//config/params:go_default_library", "//consensus-types/primitives:go_default_library", + "//network/http:go_default_library", "//proto/eth/v2:go_default_library", "//runtime/version:go_default_library", "//time/slots:go_default_library", diff --git a/beacon-chain/rpc/apimiddleware/custom_handlers.go b/beacon-chain/rpc/apimiddleware/custom_handlers.go index 753512ec5c..cdc96ccaab 100644 --- a/beacon-chain/rpc/apimiddleware/custom_handlers.go +++ b/beacon-chain/rpc/apimiddleware/custom_handlers.go @@ -8,7 +8,6 @@ import ( "fmt" "io" "net/http" - "regexp" "strconv" "strings" @@ -16,13 +15,11 @@ import ( "github.com/prysmaticlabs/prysm/v4/api/gateway/apimiddleware" "github.com/prysmaticlabs/prysm/v4/api/grpc" "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/events" + http2 "github.com/prysmaticlabs/prysm/v4/network/http" "github.com/prysmaticlabs/prysm/v4/runtime/version" "github.com/r3labs/sse/v2" ) -// match a number with optional decimals -var priorityRegex = regexp.MustCompile(`q=(\d+(?:\.\d+)?)`) - type sszConfig struct { fileName string responseJson SszResponse @@ -114,7 +111,7 @@ func handleGetSSZ( req *http.Request, config sszConfig, ) (handled bool) { - ssz, err := sszRequested(req) + ssz, err := http2.SszRequested(req) if err != nil { apimiddleware.WriteError(w, apimiddleware.InternalServerError(err), nil) return true @@ -207,44 +204,6 @@ func handlePostSSZ(m *apimiddleware.ApiProxyMiddleware, endpoint apimiddleware.E return true } -func sszRequested(req *http.Request) (bool, error) { - accept := req.Header.Values("Accept") - if len(accept) == 0 { - return false, nil - } - types := strings.Split(accept[0], ",") - currentType, currentPriority := "", 0.0 - for _, t := range types { - values := strings.Split(t, ";") - name := values[0] - if name != api.JsonMediaType && name != api.OctetStreamMediaType { - continue - } - // no params specified - if len(values) == 1 { - priority := 1.0 - if priority > currentPriority { - currentType, currentPriority = name, priority - } - continue - } - params := values[1] - match := priorityRegex.FindAllStringSubmatch(params, 1) - if len(match) != 1 { - continue - } - priority, err := strconv.ParseFloat(match[0][1], 32) - if err != nil { - return false, err - } - if priority > currentPriority { - currentType, currentPriority = name, priority - } - } - - return currentType == api.OctetStreamMediaType, nil -} - func sszPosted(req *http.Request) bool { ct, ok := req.Header["Content-Type"] if !ok { diff --git a/beacon-chain/rpc/apimiddleware/custom_handlers_test.go b/beacon-chain/rpc/apimiddleware/custom_handlers_test.go index 1703dac359..f34f5b3950 100644 --- a/beacon-chain/rpc/apimiddleware/custom_handlers_test.go +++ b/beacon-chain/rpc/apimiddleware/custom_handlers_test.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "encoding/json" - "fmt" "net/http" "net/http/httptest" "strings" @@ -43,95 +42,6 @@ func (t testSSZResponseJson) SSZFinalized() bool { return t.Finalized } -func TestSSZRequested(t *testing.T) { - t.Run("ssz_requested", func(t *testing.T) { - request := httptest.NewRequest("GET", "http://foo.example", nil) - request.Header["Accept"] = []string{api.OctetStreamMediaType} - result, err := sszRequested(request) - require.NoError(t, err) - assert.Equal(t, true, result) - }) - - t.Run("ssz_content_type_first", func(t *testing.T) { - request := httptest.NewRequest("GET", "http://foo.example", nil) - request.Header["Accept"] = []string{fmt.Sprintf("%s,%s", api.OctetStreamMediaType, api.JsonMediaType)} - result, err := sszRequested(request) - require.NoError(t, err) - assert.Equal(t, true, result) - }) - - t.Run("ssz_content_type_preferred_1", func(t *testing.T) { - request := httptest.NewRequest("GET", "http://foo.example", nil) - request.Header["Accept"] = []string{fmt.Sprintf("%s;q=0.9,%s", api.JsonMediaType, api.OctetStreamMediaType)} - result, err := sszRequested(request) - require.NoError(t, err) - assert.Equal(t, true, result) - }) - - t.Run("ssz_content_type_preferred_2", func(t *testing.T) { - request := httptest.NewRequest("GET", "http://foo.example", nil) - request.Header["Accept"] = []string{fmt.Sprintf("%s;q=0.95,%s;q=0.9", api.OctetStreamMediaType, api.JsonMediaType)} - result, err := sszRequested(request) - require.NoError(t, err) - assert.Equal(t, true, result) - }) - - t.Run("other_content_type_preferred", func(t *testing.T) { - request := httptest.NewRequest("GET", "http://foo.example", nil) - request.Header["Accept"] = []string{fmt.Sprintf("%s,%s;q=0.9", api.JsonMediaType, api.OctetStreamMediaType)} - result, err := sszRequested(request) - require.NoError(t, err) - assert.Equal(t, false, result) - }) - - t.Run("other_params", func(t *testing.T) { - request := httptest.NewRequest("GET", "http://foo.example", nil) - request.Header["Accept"] = []string{fmt.Sprintf("%s,%s;q=0.9,otherparam=xyz", api.JsonMediaType, api.OctetStreamMediaType)} - result, err := sszRequested(request) - require.NoError(t, err) - assert.Equal(t, false, result) - }) - - t.Run("no_header", func(t *testing.T) { - request := httptest.NewRequest("GET", "http://foo.example", nil) - result, err := sszRequested(request) - require.NoError(t, err) - assert.Equal(t, false, result) - }) - - t.Run("empty_header", func(t *testing.T) { - request := httptest.NewRequest("GET", "http://foo.example", nil) - request.Header["Accept"] = []string{} - result, err := sszRequested(request) - require.NoError(t, err) - assert.Equal(t, false, result) - }) - - t.Run("empty_header_value", func(t *testing.T) { - request := httptest.NewRequest("GET", "http://foo.example", nil) - request.Header["Accept"] = []string{""} - result, err := sszRequested(request) - require.NoError(t, err) - assert.Equal(t, false, result) - }) - - t.Run("other_content_type", func(t *testing.T) { - request := httptest.NewRequest("GET", "http://foo.example", nil) - request.Header["Accept"] = []string{"application/other"} - result, err := sszRequested(request) - require.NoError(t, err) - assert.Equal(t, false, result) - }) - - t.Run("garbage", func(t *testing.T) { - request := httptest.NewRequest("GET", "http://foo.example", nil) - request.Header["Accept"] = []string{"This is Sparta!!!"} - result, err := sszRequested(request) - require.NoError(t, err) - assert.Equal(t, false, result) - }) -} - func TestPrepareSSZRequestForProxying(t *testing.T) { middleware := &apimiddleware.ApiProxyMiddleware{ GatewayAddress: "http://apimiddleware.example", diff --git a/beacon-chain/rpc/eth/blob/BUILD.bazel b/beacon-chain/rpc/eth/blob/BUILD.bazel new file mode 100644 index 0000000000..e4361f9d69 --- /dev/null +++ b/beacon-chain/rpc/eth/blob/BUILD.bazel @@ -0,0 +1,47 @@ +load("@prysm//tools/go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = [ + "handlers.go", + "server.go", + "structs.go", + ], + importpath = "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/blob", + visibility = ["//visibility:public"], + deps = [ + "//beacon-chain/blockchain:go_default_library", + "//beacon-chain/db:go_default_library", + "//beacon-chain/rpc/eth/helpers:go_default_library", + "//beacon-chain/rpc/lookup:go_default_library", + "//config/fieldparams:go_default_library", + "//config/params:go_default_library", + "//consensus-types/primitives:go_default_library", + "//encoding/bytesutil:go_default_library", + "//network/http:go_default_library", + "//proto/eth/v2:go_default_library", + "//proto/migration:go_default_library", + "//proto/prysm/v1alpha1:go_default_library", + "//time/slots:go_default_library", + "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", + "@com_github_pkg_errors//:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = ["handlers_test.go"], + embed = [":go_default_library"], + deps = [ + "//beacon-chain/blockchain/testing:go_default_library", + "//beacon-chain/db/testing:go_default_library", + "//config/fieldparams:go_default_library", + "//config/params:go_default_library", + "//encoding/bytesutil:go_default_library", + "//network/http:go_default_library", + "//proto/prysm/v1alpha1: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/beacon-chain/rpc/eth/blob/handlers.go b/beacon-chain/rpc/eth/blob/handlers.go new file mode 100644 index 0000000000..7cc01547a8 --- /dev/null +++ b/beacon-chain/rpc/eth/blob/handlers.go @@ -0,0 +1,213 @@ +package blob + +import ( + "net/http" + "net/url" + "strconv" + "strings" + + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/helpers" + "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/lookup" + field_params "github.com/prysmaticlabs/prysm/v4/config/fieldparams" + "github.com/prysmaticlabs/prysm/v4/config/params" + "github.com/prysmaticlabs/prysm/v4/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v4/encoding/bytesutil" + http2 "github.com/prysmaticlabs/prysm/v4/network/http" + ethpb "github.com/prysmaticlabs/prysm/v4/proto/eth/v2" + "github.com/prysmaticlabs/prysm/v4/proto/migration" + eth "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v4/time/slots" +) + +// Blobs is an HTTP handler for Beacon API getBlobs. +func (s *Server) Blobs(w http.ResponseWriter, r *http.Request) { + var sidecars []*eth.BlobSidecar + var root []byte + + indices := parseIndices(r.URL) + segments := strings.Split(r.URL.Path, "/") + blockId := segments[len(segments)-1] + switch blockId { + case "genesis": + errJson := &http2.DefaultErrorJson{ + Message: "blobs are not supported for Phase 0 fork", + Code: http.StatusBadRequest, + } + http2.WriteError(w, errJson) + return + case "head": + var err error + root, err = s.ChainInfoFetcher.HeadRoot(r.Context()) + if err != nil { + errJson := &http2.DefaultErrorJson{ + Message: errors.Wrapf(err, "could not retrieve head root").Error(), + Code: http.StatusInternalServerError, + } + http2.WriteError(w, errJson) + return + } + case "finalized": + fcp := s.ChainInfoFetcher.FinalizedCheckpt() + if fcp == nil { + errJson := &http2.DefaultErrorJson{ + Message: "received nil finalized checkpoint", + Code: http.StatusInternalServerError, + } + http2.WriteError(w, errJson) + return + } + root = fcp.Root + case "justified": + jcp := s.ChainInfoFetcher.CurrentJustifiedCheckpt() + if jcp == nil { + errJson := &http2.DefaultErrorJson{ + Message: "received nil justified checkpoint", + Code: http.StatusInternalServerError, + } + http2.WriteError(w, errJson) + return + } + root = jcp.Root + default: + if bytesutil.IsHex([]byte(blockId)) { + var err error + root, err = hexutil.Decode(blockId) + if err != nil { + errJson := &http2.DefaultErrorJson{ + Message: errors.Wrap(err, "could not decode block ID into hex").Error(), + Code: http.StatusInternalServerError, + } + http2.WriteError(w, errJson) + return + } + } else { + slot, err := strconv.ParseUint(blockId, 10, 64) + if err != nil { + errJson := &http2.DefaultErrorJson{ + Message: lookup.NewBlockIdParseError(err).Error(), + Code: http.StatusBadRequest, + } + http2.WriteError(w, errJson) + return + } + denebStart, err := slots.EpochStart(params.BeaconConfig().DenebForkEpoch) + if err != nil { + errJson := &http2.DefaultErrorJson{ + Message: errors.Wrap(err, "could not calculate Deneb start slot").Error(), + Code: http.StatusInternalServerError, + } + http2.WriteError(w, errJson) + return + } + if primitives.Slot(slot) < denebStart { + errJson := &http2.DefaultErrorJson{ + Message: "blobs are not supported before Deneb fork", + Code: http.StatusBadRequest, + } + http2.WriteError(w, errJson) + return + } + sidecars, err = s.BeaconDB.BlobSidecarsBySlot(r.Context(), primitives.Slot(slot), indices...) + if err != nil { + errJson := &http2.DefaultErrorJson{ + Message: errors.Wrapf(err, "could not retrieve blobs for slot %d", slot).Error(), + Code: http.StatusInternalServerError, + } + http2.WriteError(w, errJson) + return + } + http2.WriteJson(w, buildSidecardsResponse(sidecars)) + return + } + } + + var err error + sidecars, err = s.BeaconDB.BlobSidecarsByRoot(r.Context(), bytesutil.ToBytes32(root), indices...) + if err != nil { + errJson := &http2.DefaultErrorJson{ + Message: errors.Wrapf(err, "could not retrieve blobs for root %#x", root).Error(), + Code: http.StatusInternalServerError, + } + http2.WriteError(w, errJson) + return + } + + ssz, err := http2.SszRequested(r) + if err != nil { + errJson := &http2.DefaultErrorJson{ + Message: err.Error(), + Code: http.StatusInternalServerError, + } + http2.WriteError(w, errJson) + return + } + + if ssz { + v2sidecars, err := migration.V1Alpha1BlobSidecarsToV2(sidecars) + if err != nil { + errJson := &http2.DefaultErrorJson{ + Message: err.Error(), + Code: http.StatusInternalServerError, + } + http2.WriteError(w, errJson) + return + } + sidecarResp := ðpb.BlobSidecars{ + Sidecars: v2sidecars, + } + sszResp, err := sidecarResp.MarshalSSZ() + if err != nil { + errJson := &http2.DefaultErrorJson{ + Message: err.Error(), + Code: http.StatusInternalServerError, + } + http2.WriteError(w, errJson) + return + } + http2.WriteSsz(w, sszResp, "blob_sidecars.ssz") + return + } + + http2.WriteJson(w, buildSidecardsResponse(sidecars)) +} + +// parseIndices filters out invalid and duplicate blob indices +func parseIndices(url *url.URL) []uint64 { + query := url.Query() + helpers.NormalizeQueryValues(query) + rawIndices := query["indices"] + indices := make([]uint64, 0, field_params.MaxBlobsPerBlock) +loop: + for _, raw := range rawIndices { + ix, err := strconv.ParseUint(raw, 10, 64) + if err != nil { + continue + } + for i := range indices { + if ix == indices[i] || ix >= field_params.MaxBlobsPerBlock { + continue loop + } + } + indices = append(indices, ix) + } + return indices +} + +func buildSidecardsResponse(sidecars []*eth.BlobSidecar) *SidecarsResponse { + resp := &SidecarsResponse{Data: make([]*Sidecar, len(sidecars))} + for i, sc := range sidecars { + resp.Data[i] = &Sidecar{ + BlockRoot: hexutil.Encode(sc.BlockRoot), + Index: strconv.FormatUint(sc.Index, 10), + Slot: strconv.FormatUint(uint64(sc.Slot), 10), + BlockParentRoot: hexutil.Encode(sc.BlockParentRoot), + ProposerIndex: strconv.FormatUint(uint64(sc.ProposerIndex), 10), + Blob: hexutil.Encode(sc.Blob), + KZGCommitment: hexutil.Encode(sc.KzgCommitment), + KZGProof: hexutil.Encode(sc.KzgProof), + } + } + return resp +} diff --git a/beacon-chain/rpc/eth/blob/handlers_test.go b/beacon-chain/rpc/eth/blob/handlers_test.go new file mode 100644 index 0000000000..13aed5d020 --- /dev/null +++ b/beacon-chain/rpc/eth/blob/handlers_test.go @@ -0,0 +1,303 @@ +package blob + +import ( + "bytes" + "context" + "encoding/json" + "net/http" + "net/http/httptest" + "net/url" + "strings" + "testing" + + "github.com/ethereum/go-ethereum/common/hexutil" + mockChain "github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain/testing" + testDB "github.com/prysmaticlabs/prysm/v4/beacon-chain/db/testing" + fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams" + "github.com/prysmaticlabs/prysm/v4/config/params" + "github.com/prysmaticlabs/prysm/v4/encoding/bytesutil" + http2 "github.com/prysmaticlabs/prysm/v4/network/http" + eth "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v4/testing/assert" + "github.com/prysmaticlabs/prysm/v4/testing/require" +) + +func TestParseIndices(t *testing.T) { + assert.DeepEqual(t, []uint64{1, 2, 3}, parseIndices(&url.URL{RawQuery: "indices=1,2,foo,1&indices=3,1&bar=bar"})) +} + +func TestBlobs(t *testing.T) { + params.SetupTestConfigCleanup(t) + cfg := params.BeaconConfig().Copy() + cfg.DenebForkEpoch = 1 + params.OverrideBeaconConfig(cfg) + + db := testDB.SetupDB(t) + blockroot := bytesutil.PadTo([]byte("blockroot"), 32) + require.NoError(t, db.SaveBlobSidecar(context.Background(), []*eth.BlobSidecar{ + { + BlockRoot: blockroot, + Index: 0, + Slot: 123, + BlockParentRoot: []byte("blockparentroot"), + ProposerIndex: 123, + Blob: []byte("blob0"), + KzgCommitment: []byte("kzgcommitment0"), + KzgProof: []byte("kzgproof0"), + }, + { + BlockRoot: blockroot, + Index: 1, + Slot: 123, + BlockParentRoot: []byte("blockparentroot"), + ProposerIndex: 123, + Blob: []byte("blob1"), + KzgCommitment: []byte("kzgcommitment1"), + KzgProof: []byte("kzgproof1"), + }, + { + BlockRoot: blockroot, + Index: 2, + Slot: 123, + BlockParentRoot: []byte("blockparentroot"), + ProposerIndex: 123, + Blob: []byte("blob2"), + KzgCommitment: []byte("kzgcommitment2"), + KzgProof: []byte("kzgproof2"), + }, + { + BlockRoot: blockroot, + Index: 3, + Slot: 123, + BlockParentRoot: []byte("blockparentroot"), + ProposerIndex: 123, + Blob: []byte("blob3"), + KzgCommitment: []byte("kzgcommitment3"), + KzgProof: []byte("kzgproof3"), + }, + })) + + t.Run("genesis", func(t *testing.T) { + u := "http://foo.example/genesis" + request := httptest.NewRequest("GET", u, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + s := &Server{} + + s.Blobs(writer, request) + + assert.Equal(t, http.StatusBadRequest, writer.Code) + e := &http2.DefaultErrorJson{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) + assert.Equal(t, http.StatusBadRequest, e.Code) + assert.Equal(t, "blobs are not supported for Phase 0 fork", e.Message) + }) + t.Run("head", func(t *testing.T) { + u := "http://foo.example/head" + request := httptest.NewRequest("GET", u, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + s := &Server{ + ChainInfoFetcher: &mockChain.ChainService{Root: blockroot}, + BeaconDB: db, + } + + s.Blobs(writer, request) + + assert.Equal(t, http.StatusOK, writer.Code) + resp := &SidecarsResponse{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) + require.Equal(t, 4, len(resp.Data)) + sidecar := resp.Data[0] + require.NotNil(t, sidecar) + assert.Equal(t, "0x626c6f636b726f6f740000000000000000000000000000000000000000000000", sidecar.BlockRoot) + assert.Equal(t, "0", sidecar.Index) + assert.Equal(t, "123", sidecar.Slot) + assert.Equal(t, "0x626c6f636b706172656e74726f6f74", sidecar.BlockParentRoot) + assert.Equal(t, "123", sidecar.ProposerIndex) + assert.Equal(t, "0x626c6f6230", sidecar.Blob) + assert.Equal(t, "0x6b7a67636f6d6d69746d656e7430", sidecar.KZGCommitment) + assert.Equal(t, "0x6b7a6770726f6f6630", sidecar.KZGProof) + sidecar = resp.Data[1] + require.NotNil(t, sidecar) + assert.Equal(t, "0x626c6f636b726f6f740000000000000000000000000000000000000000000000", sidecar.BlockRoot) + assert.Equal(t, "1", sidecar.Index) + assert.Equal(t, "123", sidecar.Slot) + assert.Equal(t, "0x626c6f636b706172656e74726f6f74", sidecar.BlockParentRoot) + assert.Equal(t, "123", sidecar.ProposerIndex) + assert.Equal(t, "0x626c6f6231", sidecar.Blob) + assert.Equal(t, "0x6b7a67636f6d6d69746d656e7431", sidecar.KZGCommitment) + assert.Equal(t, "0x6b7a6770726f6f6631", sidecar.KZGProof) + sidecar = resp.Data[2] + require.NotNil(t, sidecar) + assert.Equal(t, "0x626c6f636b726f6f740000000000000000000000000000000000000000000000", sidecar.BlockRoot) + assert.Equal(t, "2", sidecar.Index) + assert.Equal(t, "123", sidecar.Slot) + assert.Equal(t, "0x626c6f636b706172656e74726f6f74", sidecar.BlockParentRoot) + assert.Equal(t, "123", sidecar.ProposerIndex) + assert.Equal(t, "0x626c6f6232", sidecar.Blob) + assert.Equal(t, "0x6b7a67636f6d6d69746d656e7432", sidecar.KZGCommitment) + assert.Equal(t, "0x6b7a6770726f6f6632", sidecar.KZGProof) + sidecar = resp.Data[3] + require.NotNil(t, sidecar) + assert.Equal(t, "0x626c6f636b726f6f740000000000000000000000000000000000000000000000", sidecar.BlockRoot) + assert.Equal(t, "3", sidecar.Index) + assert.Equal(t, "123", sidecar.Slot) + assert.Equal(t, "0x626c6f636b706172656e74726f6f74", sidecar.BlockParentRoot) + assert.Equal(t, "123", sidecar.ProposerIndex) + assert.Equal(t, "0x626c6f6233", sidecar.Blob) + assert.Equal(t, "0x6b7a67636f6d6d69746d656e7433", sidecar.KZGCommitment) + assert.Equal(t, "0x6b7a6770726f6f6633", sidecar.KZGProof) + }) + t.Run("finalized", func(t *testing.T) { + u := "http://foo.example/finalized" + request := httptest.NewRequest("GET", u, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + s := &Server{ + ChainInfoFetcher: &mockChain.ChainService{FinalizedCheckPoint: ð.Checkpoint{Root: blockroot}}, + BeaconDB: db, + } + + s.Blobs(writer, request) + + assert.Equal(t, http.StatusOK, writer.Code) + resp := &SidecarsResponse{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) + require.Equal(t, 4, len(resp.Data)) + }) + t.Run("justified", func(t *testing.T) { + u := "http://foo.example/justified" + request := httptest.NewRequest("GET", u, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + s := &Server{ + ChainInfoFetcher: &mockChain.ChainService{CurrentJustifiedCheckPoint: ð.Checkpoint{Root: blockroot}}, + BeaconDB: db, + } + + s.Blobs(writer, request) + + assert.Equal(t, http.StatusOK, writer.Code) + resp := &SidecarsResponse{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) + require.Equal(t, 4, len(resp.Data)) + }) + t.Run("root", func(t *testing.T) { + u := "http://foo.example/" + hexutil.Encode(blockroot) + request := httptest.NewRequest("GET", u, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + s := &Server{ + BeaconDB: db, + } + + s.Blobs(writer, request) + + assert.Equal(t, http.StatusOK, writer.Code) + resp := &SidecarsResponse{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) + require.Equal(t, 4, len(resp.Data)) + }) + t.Run("slot", func(t *testing.T) { + u := "http://foo.example/123" + request := httptest.NewRequest("GET", u, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + s := &Server{ + BeaconDB: db, + } + + s.Blobs(writer, request) + + assert.Equal(t, http.StatusOK, writer.Code) + resp := &SidecarsResponse{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) + require.Equal(t, 4, len(resp.Data)) + }) + t.Run("one blob only", func(t *testing.T) { + u := "http://foo.example/123?indices=2" + request := httptest.NewRequest("GET", u, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + s := &Server{ + BeaconDB: db, + } + + s.Blobs(writer, request) + + assert.Equal(t, http.StatusOK, writer.Code) + resp := &SidecarsResponse{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) + require.Equal(t, 1, len(resp.Data)) + sidecar := resp.Data[0] + require.NotNil(t, sidecar) + assert.Equal(t, "0x626c6f636b726f6f740000000000000000000000000000000000000000000000", sidecar.BlockRoot) + assert.Equal(t, "2", sidecar.Index) + assert.Equal(t, "123", sidecar.Slot) + assert.Equal(t, "0x626c6f636b706172656e74726f6f74", sidecar.BlockParentRoot) + assert.Equal(t, "123", sidecar.ProposerIndex) + assert.Equal(t, "0x626c6f6232", sidecar.Blob) + assert.Equal(t, "0x6b7a67636f6d6d69746d656e7432", sidecar.KZGCommitment) + assert.Equal(t, "0x6b7a6770726f6f6632", sidecar.KZGProof) + }) + t.Run("slot before Deneb fork", func(t *testing.T) { + u := "http://foo.example/31" + request := httptest.NewRequest("GET", u, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + s := &Server{} + + s.Blobs(writer, request) + + assert.Equal(t, http.StatusBadRequest, writer.Code) + e := &http2.DefaultErrorJson{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) + assert.Equal(t, http.StatusBadRequest, e.Code) + assert.Equal(t, "blobs are not supported before Deneb fork", e.Message) + }) + t.Run("malformed block ID", func(t *testing.T) { + u := "http://foo.example/foo" + request := httptest.NewRequest("GET", u, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + s := &Server{} + + s.Blobs(writer, request) + + assert.Equal(t, http.StatusBadRequest, writer.Code) + e := &http2.DefaultErrorJson{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) + assert.Equal(t, http.StatusBadRequest, e.Code) + assert.Equal(t, true, strings.Contains(e.Message, "could not parse block ID")) + }) + t.Run("ssz", func(t *testing.T) { + require.NoError(t, db.SaveBlobSidecar(context.Background(), []*eth.BlobSidecar{ + { + BlockRoot: blockroot, + Index: 0, + Slot: 3, + BlockParentRoot: make([]byte, fieldparams.RootLength), + ProposerIndex: 123, + Blob: make([]byte, fieldparams.BlobLength), + KzgCommitment: make([]byte, fieldparams.BLSPubkeyLength), + KzgProof: make([]byte, fieldparams.BLSPubkeyLength), + }, + })) + u := "http://foo.example/finalized?indices=0" + request := httptest.NewRequest("GET", u, nil) + request.Header.Add("Accept", "application/octet-stream") + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + s := &Server{ + ChainInfoFetcher: &mockChain.ChainService{FinalizedCheckPoint: ð.Checkpoint{Root: blockroot}}, + BeaconDB: db, + } + + s.Blobs(writer, request) + + assert.Equal(t, http.StatusOK, writer.Code) + assert.Equal(t, len(writer.Body.Bytes()), 131260) + assert.Equal(t, true, strings.HasPrefix(hexutil.Encode(writer.Body.Bytes()), "0x04000000626c6f636b726f6f7400000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000007b")) + }) +} diff --git a/beacon-chain/rpc/eth/blob/server.go b/beacon-chain/rpc/eth/blob/server.go new file mode 100644 index 0000000000..5fd5e37f31 --- /dev/null +++ b/beacon-chain/rpc/eth/blob/server.go @@ -0,0 +1,11 @@ +package blob + +import ( + "github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain" + "github.com/prysmaticlabs/prysm/v4/beacon-chain/db" +) + +type Server struct { + ChainInfoFetcher blockchain.ChainInfoFetcher + BeaconDB db.ReadOnlyDatabase +} diff --git a/beacon-chain/rpc/eth/blob/structs.go b/beacon-chain/rpc/eth/blob/structs.go new file mode 100644 index 0000000000..e5676c9313 --- /dev/null +++ b/beacon-chain/rpc/eth/blob/structs.go @@ -0,0 +1,16 @@ +package blob + +type SidecarsResponse struct { + Data []*Sidecar `json:"data"` +} + +type Sidecar struct { + BlockRoot string `json:"block_root"` + Index string `json:"index"` + Slot string `json:"slot"` + BlockParentRoot string `json:"block_parent_root"` + ProposerIndex string `json:"proposer_index"` + Blob string `json:"blob"` + KZGCommitment string `json:"kzg_commitment"` + KZGProof string `json:"kzg_proof"` +} diff --git a/beacon-chain/rpc/eth/helpers/BUILD.bazel b/beacon-chain/rpc/eth/helpers/BUILD.bazel index d053523fab..3c695ede87 100644 --- a/beacon-chain/rpc/eth/helpers/BUILD.bazel +++ b/beacon-chain/rpc/eth/helpers/BUILD.bazel @@ -4,6 +4,7 @@ go_library( name = "go_default_library", srcs = [ "error_handling.go", + "http.go", "sync.go", "validator_status.go", ], @@ -32,6 +33,7 @@ go_library( go_test( name = "go_default_test", srcs = [ + "http_test.go", "sync_test.go", "validator_status_test.go", ], diff --git a/beacon-chain/rpc/eth/helpers/http.go b/beacon-chain/rpc/eth/helpers/http.go new file mode 100644 index 0000000000..0056dda1d3 --- /dev/null +++ b/beacon-chain/rpc/eth/helpers/http.go @@ -0,0 +1,17 @@ +package helpers + +import ( + "net/url" + "strings" +) + +// NormalizeQueryValues replaces comma-separated values with individual values +func NormalizeQueryValues(queryParams url.Values) { + for key, vals := range queryParams { + splitVals := make([]string, 0) + for _, v := range vals { + splitVals = append(splitVals, strings.Split(v, ",")...) + } + queryParams[key] = splitVals + } +} diff --git a/beacon-chain/rpc/eth/helpers/http_test.go b/beacon-chain/rpc/eth/helpers/http_test.go new file mode 100644 index 0000000000..bcc1052ba5 --- /dev/null +++ b/beacon-chain/rpc/eth/helpers/http_test.go @@ -0,0 +1,21 @@ +package helpers + +import ( + "testing" + + "github.com/prysmaticlabs/prysm/v4/testing/assert" + "github.com/prysmaticlabs/prysm/v4/testing/require" +) + +func TestNormalizeQueryValues(t *testing.T) { + input := make(map[string][]string) + input["key"] = []string{"value1", "value2,value3,value4", "value5"} + + NormalizeQueryValues(input) + require.Equal(t, 5, len(input["key"])) + assert.Equal(t, "value1", input["key"][0]) + assert.Equal(t, "value2", input["key"][1]) + assert.Equal(t, "value3", input["key"][2]) + assert.Equal(t, "value4", input["key"][3]) + assert.Equal(t, "value5", input["key"][4]) +} diff --git a/beacon-chain/rpc/service.go b/beacon-chain/rpc/service.go index 95cb84fc4c..bdc090602d 100644 --- a/beacon-chain/rpc/service.go +++ b/beacon-chain/rpc/service.go @@ -32,6 +32,7 @@ import ( "github.com/prysmaticlabs/prysm/v4/beacon-chain/p2p" "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/core" "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/beacon" + "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/blob" rpcBuilder "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/builder" "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/debug" "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/events" @@ -232,6 +233,12 @@ func (s *Service) Start() { } s.cfg.Router.HandleFunc("/eth/v1/builder/states/{state_id}/expected_withdrawals", builderServer.ExpectedWithdrawals).Methods(http.MethodGet) + blobServer := &blob.Server{ + ChainInfoFetcher: s.cfg.ChainInfoFetcher, + BeaconDB: s.cfg.BeaconDB, + } + s.cfg.Router.HandleFunc("/eth/v1/beacon/blobs/{block_id}", blobServer.Blobs) + coreService := &core.Service{ HeadFetcher: s.cfg.HeadFetcher, GenesisTimeFetcher: s.cfg.GenesisTimeFetcher, diff --git a/beacon-chain/sync/rpc.go b/beacon-chain/sync/rpc.go index 3b3a355ed7..874e0ec46f 100644 --- a/beacon-chain/sync/rpc.go +++ b/beacon-chain/sync/rpc.go @@ -126,10 +126,13 @@ func (s *Service) registerRPC(baseTopic string, handle rpcHandler) { s.cfg.p2p.SetStreamHandler(topic, func(stream network.Stream) { defer func() { if r := recover(); r != nil { - log.WithField("error", r).Error("Panic occurred") - log.Errorf("%s", debug.Stack()) + log.WithField("error", r). + WithField("recovered_at", "registerRPC"). + WithField("stack", string(debug.Stack())). + Error("Panic occurred") } }() + ctx, cancel := context.WithTimeout(s.ctx, ttfbTimeout) defer cancel() diff --git a/beacon-chain/sync/rpc_chunked_response.go b/beacon-chain/sync/rpc_chunked_response.go index 14a0679e1c..2ff9e6afca 100644 --- a/beacon-chain/sync/rpc_chunked_response.go +++ b/beacon-chain/sync/rpc_chunked_response.go @@ -59,6 +59,12 @@ func WriteBlockChunk(stream libp2pcore.Stream, tor blockchain.TemporalOracle, en return err } obtainedCtx = digest[:] + case version.Deneb: + digest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().DenebForkEpoch, valRoot[:]) + if err != nil { + return err + } + obtainedCtx = digest[:] default: return errors.Wrapf(ErrUnrecognizedVersion, "block version %d is not recognized", blk.Version()) } diff --git a/beacon-chain/sync/subscriber.go b/beacon-chain/sync/subscriber.go index 730ea6b298..573564c2bc 100644 --- a/beacon-chain/sync/subscriber.go +++ b/beacon-chain/sync/subscriber.go @@ -201,8 +201,10 @@ func (s *Service) subscribeWithBase(topic string, validator wrappedVal, handle s defer func() { if r := recover(); r != nil { tracing.AnnotateError(span, fmt.Errorf("panic occurred: %v", r)) - log.WithField("error", r).Error("Panic occurred") - debug.PrintStack() + log.WithField("error", r). + WithField("recovered_at", "subscribeWithBase"). + WithField("stack", string(debug.Stack())). + Error("Panic occurred") } }() diff --git a/config/params/loader_test.go b/config/params/loader_test.go index e81b1d4a31..da2c24a08c 100644 --- a/config/params/loader_test.go +++ b/config/params/loader_test.go @@ -129,8 +129,9 @@ func TestModifiedE2E(t *testing.T) { c := params.E2ETestConfig().Copy() c.DepositContractAddress = "0x4242424242424242424242424242424242424242" c.TerminalTotalDifficulty = "0" - c.AltairForkEpoch = 0 - c.BellatrixForkEpoch = 0 + c.AltairForkEpoch = 112 + c.BellatrixForkEpoch = 123 + c.CapellaForkEpoch = 235 c.DenebForkEpoch = 358 y := params.ConfigToYaml(c) cfg, err := params.UnmarshalConfig(y, nil) diff --git a/consensus-types/blocks/factory.go b/consensus-types/blocks/factory.go index 5554067f9b..9e2dd9a3f7 100644 --- a/consensus-types/blocks/factory.go +++ b/consensus-types/blocks/factory.go @@ -360,6 +360,10 @@ func BuildSignedBeaconBlockFromExecutionPayload( // This is particularly useful for using the values from API calls. func BeaconBlockContainerToSignedBeaconBlock(obj *eth.BeaconBlockContainer) (interfaces.ReadOnlySignedBeaconBlock, error) { switch obj.Block.(type) { + case *eth.BeaconBlockContainer_BlindedDenebBlock: + return NewSignedBeaconBlock(obj.GetBlindedDenebBlock()) + case *eth.BeaconBlockContainer_DenebBlock: + return NewSignedBeaconBlock(obj.GetDenebBlock()) case *eth.BeaconBlockContainer_BlindedCapellaBlock: return NewSignedBeaconBlock(obj.GetBlindedCapellaBlock()) case *eth.BeaconBlockContainer_CapellaBlock: diff --git a/consensus-types/payload-attribute/getters.go b/consensus-types/payload-attribute/getters.go index f59097d222..79c60174a3 100644 --- a/consensus-types/payload-attribute/getters.go +++ b/consensus-types/payload-attribute/getters.go @@ -61,7 +61,7 @@ func (a *data) PbV2() (*enginev1.PayloadAttributesV2, error) { if a == nil { return nil, errNilPayloadAttribute } - if a.version != version.Capella { + if a.version < version.Capella { return nil, consensus_types.ErrNotSupported("PayloadAttributePbV2", a.version) } if a.timeStamp == 0 && len(a.prevRandao) == 0 { diff --git a/proto/engine/v1/json_marshal_unmarshal.go b/proto/engine/v1/json_marshal_unmarshal.go index 83324f495c..25208f47c9 100644 --- a/proto/engine/v1/json_marshal_unmarshal.go +++ b/proto/engine/v1/json_marshal_unmarshal.go @@ -14,8 +14,11 @@ import ( "github.com/prysmaticlabs/prysm/v4/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v4/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v4/runtime/version" + log "github.com/sirupsen/logrus" ) +var errExecutionUnmarshal = errors.New("unable to unmarshal execution engine data") + // PayloadIDBytes defines a custom type for Payload IDs used by the engine API // client with proper JSON Marshal and Unmarshal methods to hex. type PayloadIDBytes [8]byte @@ -34,8 +37,8 @@ type ExecutionBlock struct { Transactions []*gethtypes.Transaction `json:"transactions"` TotalDifficulty string `json:"totalDifficulty"` Withdrawals []*Withdrawal `json:"withdrawals"` - DataGasUsed uint64 `json:"dataGasUsed"` - ExcessDataGas uint64 `json:"excessDataGas"` + DataGasUsed *hexutil.Uint64 `json:"dataGasUsed"` + ExcessDataGas *hexutil.Uint64 `json:"excessDataGas"` } func (e *ExecutionBlock) MarshalJSON() ([]byte, error) { @@ -108,18 +111,22 @@ func (e *ExecutionBlock) UnmarshalJSON(enc []byte) error { edg, has := decoded["excessDataGas"] if has && edg != nil { e.Version = version.Deneb - e.ExcessDataGas, err = hexutil.DecodeUint64(edg.(string)) + uedg, err := hexutil.DecodeUint64(edg.(string)) if err != nil { return err } + *e.ExcessDataGas = hexutil.Uint64(uedg) } + dgu, has := decoded["dataGasUsed"] + log.Error(has, dgu != nil) if has && dgu != nil { e.Version = version.Deneb - e.DataGasUsed, err = hexutil.DecodeUint64(dgu.(string)) + udgu, err := hexutil.DecodeUint64(dgu.(string)) if err != nil { return err } + *e.DataGasUsed = hexutil.Uint64(udgu) } } diff --git a/proto/eth/v2/BUILD.bazel b/proto/eth/v2/BUILD.bazel index ff558827ac..cfc26696e2 100644 --- a/proto/eth/v2/BUILD.bazel +++ b/proto/eth/v2/BUILD.bazel @@ -50,6 +50,8 @@ ssz_gen_marshal( "SignedBlsToExecutionChange", "SignedBlindedBlobSidecar", "BlindedBlobSidecar", + "BlobSidecar", + "BlobSidecars", ], ) diff --git a/proto/eth/v2/blobs.pb.go b/proto/eth/v2/blobs.pb.go index f89be70d2d..4c5318ddde 100755 --- a/proto/eth/v2/blobs.pb.go +++ b/proto/eth/v2/blobs.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.30.0 -// protoc v3.15.8 +// protoc v4.23.3 // source: proto/eth/v2/blobs.proto package eth @@ -28,7 +28,7 @@ type BlobSidecars struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Sidecars []*BlobSidecar `protobuf:"bytes,1,rep,name=sidecars,proto3" json:"sidecars,omitempty"` + Sidecars []*BlobSidecar `protobuf:"bytes,1,rep,name=sidecars,proto3" json:"sidecars,omitempty" ssz-max:"4"` } func (x *BlobSidecars) Reset() { @@ -448,98 +448,98 @@ var file_proto_eth_v2_blobs_proto_rawDesc = []byte{ 0x6c, 0x6f, 0x62, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x1a, 0x1b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x65, 0x78, 0x74, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x48, 0x0a, 0x0c, 0x42, 0x6c, 0x6f, 0x62, - 0x53, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x73, 0x12, 0x38, 0x0a, 0x08, 0x73, 0x69, 0x64, 0x65, + 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x4f, 0x0a, 0x0c, 0x42, 0x6c, 0x6f, 0x62, + 0x53, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x73, 0x12, 0x3f, 0x0a, 0x08, 0x73, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x6c, 0x6f, - 0x62, 0x53, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x52, 0x08, 0x73, 0x69, 0x64, 0x65, 0x63, 0x61, - 0x72, 0x73, 0x22, 0xc5, 0x03, 0x0a, 0x0b, 0x42, 0x6c, 0x6f, 0x62, 0x53, 0x69, 0x64, 0x65, 0x63, - 0x61, 0x72, 0x12, 0x25, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x72, 0x6f, 0x6f, 0x74, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, - 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, - 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, - 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, - 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, + 0x62, 0x53, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x42, 0x05, 0x92, 0xb5, 0x18, 0x01, 0x34, 0x52, + 0x08, 0x73, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x73, 0x22, 0xc5, 0x03, 0x0a, 0x0b, 0x42, 0x6c, + 0x6f, 0x62, 0x53, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x12, 0x25, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, + 0x63, 0x6b, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, + 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, + 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, + 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x34, 0x2f, 0x63, 0x6f, 0x6e, 0x73, + 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, + 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, + 0x74, 0x12, 0x32, 0x0a, 0x11, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x70, 0x61, 0x72, 0x65, 0x6e, + 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, + 0x18, 0x02, 0x33, 0x32, 0x52, 0x0f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x50, 0x61, 0x72, 0x65, 0x6e, + 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x76, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, + 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, + 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x34, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, - 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x32, 0x0a, 0x11, 0x62, 0x6c, - 0x6f, 0x63, 0x6b, 0x5f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0f, 0x62, - 0x6c, 0x6f, 0x63, 0x6b, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x76, - 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, - 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x34, 0x2f, 0x63, 0x6f, - 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, - 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, - 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x1e, 0x0a, 0x04, 0x62, 0x6c, 0x6f, 0x62, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x0c, 0x42, 0x0a, 0x8a, 0xb5, 0x18, 0x06, 0x31, 0x33, 0x31, 0x30, 0x37, 0x32, - 0x52, 0x04, 0x62, 0x6c, 0x6f, 0x62, 0x12, 0x2d, 0x0a, 0x0e, 0x6b, 0x7a, 0x67, 0x5f, 0x63, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, - 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x52, 0x0d, 0x6b, 0x7a, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x69, - 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x09, 0x6b, 0x7a, 0x67, 0x5f, 0x70, 0x72, 0x6f, - 0x6f, 0x66, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, - 0x52, 0x08, 0x6b, 0x7a, 0x67, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x22, 0x71, 0x0a, 0x11, 0x53, 0x69, - 0x67, 0x6e, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x62, 0x53, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x12, - 0x36, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, - 0x76, 0x32, 0x2e, 0x42, 0x6c, 0x6f, 0x62, 0x53, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x52, 0x07, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, - 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x4d, 0x0a, - 0x0e, 0x42, 0x6c, 0x6f, 0x62, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, - 0x25, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x62, 0x6c, 0x6f, - 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x7f, 0x0a, 0x18, - 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x6c, 0x6f, - 0x62, 0x53, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x12, 0x3d, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x65, 0x74, 0x68, 0x65, - 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x6c, 0x69, 0x6e, - 0x64, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x62, 0x53, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x52, 0x07, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, - 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0xd1, 0x03, - 0x0a, 0x12, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x62, 0x53, 0x69, 0x64, - 0x65, 0x63, 0x61, 0x72, 0x12, 0x25, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x72, 0x6f, - 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, - 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x69, - 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, - 0x78, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x42, - 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, - 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x34, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, - 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, - 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x32, 0x0a, 0x11, - 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x6f, 0x6f, - 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, - 0x0f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x6f, 0x6f, 0x74, - 0x12, 0x76, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, - 0x65, 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, - 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x34, 0x2f, - 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, - 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x70, 0x6f, - 0x73, 0x65, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x23, 0x0a, 0x09, 0x62, 0x6c, 0x6f, 0x62, - 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, - 0x02, 0x33, 0x32, 0x52, 0x08, 0x62, 0x6c, 0x6f, 0x62, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x2d, 0x0a, + 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0d, + 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x1e, 0x0a, + 0x04, 0x62, 0x6c, 0x6f, 0x62, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x0a, 0x8a, 0xb5, 0x18, + 0x06, 0x31, 0x33, 0x31, 0x30, 0x37, 0x32, 0x52, 0x04, 0x62, 0x6c, 0x6f, 0x62, 0x12, 0x2d, 0x0a, 0x0e, 0x6b, 0x7a, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x52, 0x0d, 0x6b, 0x7a, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x09, 0x6b, 0x7a, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x52, 0x08, 0x6b, 0x7a, 0x67, 0x50, 0x72, 0x6f, 0x6f, - 0x66, 0x42, 0x7b, 0x0a, 0x13, 0x6f, 0x72, 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x42, 0x0a, 0x42, 0x6c, 0x6f, 0x62, 0x73, 0x50, - 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x32, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, - 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x34, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, - 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x3b, 0x65, 0x74, 0x68, 0xaa, 0x02, 0x0f, 0x45, 0x74, 0x68, - 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, 0x74, 0x68, 0x2e, 0x56, 0x32, 0xca, 0x02, 0x0f, 0x45, - 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x45, 0x74, 0x68, 0x5c, 0x76, 0x32, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x66, 0x22, 0x71, 0x0a, 0x11, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x62, 0x53, + 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x12, 0x36, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x6c, 0x6f, 0x62, 0x53, 0x69, + 0x64, 0x65, 0x63, 0x61, 0x72, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x24, + 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x22, 0x4d, 0x0a, 0x0e, 0x42, 0x6c, 0x6f, 0x62, 0x49, 0x64, 0x65, 0x6e, + 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x25, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, + 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, + 0x33, 0x32, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x14, 0x0a, + 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x6e, + 0x64, 0x65, 0x78, 0x22, 0x7f, 0x0a, 0x18, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x6c, 0x69, + 0x6e, 0x64, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x62, 0x53, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x12, + 0x3d, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x23, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, + 0x76, 0x32, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x62, 0x53, 0x69, + 0x64, 0x65, 0x63, 0x61, 0x72, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x24, + 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x22, 0xd1, 0x03, 0x0a, 0x12, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, + 0x42, 0x6c, 0x6f, 0x62, 0x53, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x12, 0x25, 0x0a, 0x0a, 0x62, + 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, + 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, + 0x6f, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, + 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x34, 0x2f, 0x63, 0x6f, + 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, + 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, + 0x6c, 0x6f, 0x74, 0x12, 0x32, 0x0a, 0x11, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x70, 0x61, 0x72, + 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, + 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x50, 0x61, 0x72, + 0x65, 0x6e, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x76, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x70, 0x6f, + 0x73, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x42, + 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, + 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x34, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, + 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, + 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, + 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, + 0x23, 0x0a, 0x09, 0x62, 0x6c, 0x6f, 0x62, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x08, 0x62, 0x6c, 0x6f, 0x62, + 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x2d, 0x0a, 0x0e, 0x6b, 0x7a, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, + 0x18, 0x02, 0x34, 0x38, 0x52, 0x0d, 0x6b, 0x7a, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, + 0x65, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x09, 0x6b, 0x7a, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x52, 0x08, + 0x6b, 0x7a, 0x67, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x42, 0x7b, 0x0a, 0x13, 0x6f, 0x72, 0x67, 0x2e, + 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x42, + 0x0a, 0x42, 0x6c, 0x6f, 0x62, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x32, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, + 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x34, + 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x3b, 0x65, 0x74, + 0x68, 0xaa, 0x02, 0x0f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, 0x74, 0x68, + 0x2e, 0x56, 0x32, 0xca, 0x02, 0x0f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x45, + 0x74, 0x68, 0x5c, 0x76, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/proto/eth/v2/blobs.proto b/proto/eth/v2/blobs.proto index 9fd564af25..5570330f67 100644 --- a/proto/eth/v2/blobs.proto +++ b/proto/eth/v2/blobs.proto @@ -25,7 +25,7 @@ option java_package = "org.ethereum.eth.v2"; option php_namespace = "Ethereum\\Eth\\v2"; message BlobSidecars { - repeated BlobSidecar sidecars = 1; + repeated BlobSidecar sidecars = 1 [(ethereum.eth.ext.ssz_max) = "max_blobs_per_block.size"]; } message BlobSidecar { diff --git a/proto/eth/v2/generated.ssz.go b/proto/eth/v2/generated.ssz.go index e7e608b135..9eb3ec5da6 100644 --- a/proto/eth/v2/generated.ssz.go +++ b/proto/eth/v2/generated.ssz.go @@ -1,5 +1,5 @@ // Code generated by fastssz. DO NOT EDIT. -// Hash: d16e2de4d45d122d558a635972d3c2bce0c642465acb244af5a7f10957a72a33 +// Hash: 10fbf3bf6d33b9bb3b31379c65cd6cc3bd9bc0a86e6a2395340138fe26041af0 package eth import ( @@ -5788,6 +5788,294 @@ func (b *BeaconBlockBodyDeneb) HashTreeRootWith(hh *ssz.Hasher) (err error) { return } +// MarshalSSZ ssz marshals the BlobSidecars object +func (b *BlobSidecars) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(b) +} + +// MarshalSSZTo ssz marshals the BlobSidecars object to a target array +func (b *BlobSidecars) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + offset := int(4) + + // Offset (0) 'Sidecars' + dst = ssz.WriteOffset(dst, offset) + offset += len(b.Sidecars) * 131256 + + // Field (0) 'Sidecars' + if size := len(b.Sidecars); size > 4 { + err = ssz.ErrListTooBigFn("--.Sidecars", size, 4) + return + } + for ii := 0; ii < len(b.Sidecars); ii++ { + if dst, err = b.Sidecars[ii].MarshalSSZTo(dst); err != nil { + return + } + } + + return +} + +// UnmarshalSSZ ssz unmarshals the BlobSidecars object +func (b *BlobSidecars) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size < 4 { + return ssz.ErrSize + } + + tail := buf + var o0 uint64 + + // Offset (0) 'Sidecars' + if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { + return ssz.ErrOffset + } + + if o0 < 4 { + return ssz.ErrInvalidVariableOffset + } + + // Field (0) 'Sidecars' + { + buf = tail[o0:] + num, err := ssz.DivideInt2(len(buf), 131256, 4) + if err != nil { + return err + } + b.Sidecars = make([]*BlobSidecar, num) + for ii := 0; ii < num; ii++ { + if b.Sidecars[ii] == nil { + b.Sidecars[ii] = new(BlobSidecar) + } + if err = b.Sidecars[ii].UnmarshalSSZ(buf[ii*131256 : (ii+1)*131256]); err != nil { + return err + } + } + } + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the BlobSidecars object +func (b *BlobSidecars) SizeSSZ() (size int) { + size = 4 + + // Field (0) 'Sidecars' + size += len(b.Sidecars) * 131256 + + return +} + +// HashTreeRoot ssz hashes the BlobSidecars object +func (b *BlobSidecars) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(b) +} + +// HashTreeRootWith ssz hashes the BlobSidecars object with a hasher +func (b *BlobSidecars) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'Sidecars' + { + subIndx := hh.Index() + num := uint64(len(b.Sidecars)) + if num > 4 { + err = ssz.ErrIncorrectListSize + return + } + for _, elem := range b.Sidecars { + if err = elem.HashTreeRootWith(hh); err != nil { + return + } + } + if ssz.EnableVectorizedHTR { + hh.MerkleizeWithMixinVectorizedHTR(subIndx, num, 4) + } else { + hh.MerkleizeWithMixin(subIndx, num, 4) + } + } + + if ssz.EnableVectorizedHTR { + hh.MerkleizeVectorizedHTR(indx) + } else { + hh.Merkleize(indx) + } + return +} + +// MarshalSSZ ssz marshals the BlobSidecar object +func (b *BlobSidecar) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(b) +} + +// MarshalSSZTo ssz marshals the BlobSidecar object to a target array +func (b *BlobSidecar) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + + // Field (0) 'BlockRoot' + if size := len(b.BlockRoot); size != 32 { + err = ssz.ErrBytesLengthFn("--.BlockRoot", size, 32) + return + } + dst = append(dst, b.BlockRoot...) + + // Field (1) 'Index' + dst = ssz.MarshalUint64(dst, b.Index) + + // Field (2) 'Slot' + dst = ssz.MarshalUint64(dst, uint64(b.Slot)) + + // Field (3) 'BlockParentRoot' + if size := len(b.BlockParentRoot); size != 32 { + err = ssz.ErrBytesLengthFn("--.BlockParentRoot", size, 32) + return + } + dst = append(dst, b.BlockParentRoot...) + + // Field (4) 'ProposerIndex' + dst = ssz.MarshalUint64(dst, uint64(b.ProposerIndex)) + + // Field (5) 'Blob' + if size := len(b.Blob); size != 131072 { + err = ssz.ErrBytesLengthFn("--.Blob", size, 131072) + return + } + dst = append(dst, b.Blob...) + + // Field (6) 'KzgCommitment' + if size := len(b.KzgCommitment); size != 48 { + err = ssz.ErrBytesLengthFn("--.KzgCommitment", size, 48) + return + } + dst = append(dst, b.KzgCommitment...) + + // Field (7) 'KzgProof' + if size := len(b.KzgProof); size != 48 { + err = ssz.ErrBytesLengthFn("--.KzgProof", size, 48) + return + } + dst = append(dst, b.KzgProof...) + + return +} + +// UnmarshalSSZ ssz unmarshals the BlobSidecar object +func (b *BlobSidecar) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size != 131256 { + return ssz.ErrSize + } + + // Field (0) 'BlockRoot' + if cap(b.BlockRoot) == 0 { + b.BlockRoot = make([]byte, 0, len(buf[0:32])) + } + b.BlockRoot = append(b.BlockRoot, buf[0:32]...) + + // Field (1) 'Index' + b.Index = ssz.UnmarshallUint64(buf[32:40]) + + // Field (2) 'Slot' + b.Slot = github_com_prysmaticlabs_prysm_v4_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[40:48])) + + // Field (3) 'BlockParentRoot' + if cap(b.BlockParentRoot) == 0 { + b.BlockParentRoot = make([]byte, 0, len(buf[48:80])) + } + b.BlockParentRoot = append(b.BlockParentRoot, buf[48:80]...) + + // Field (4) 'ProposerIndex' + b.ProposerIndex = github_com_prysmaticlabs_prysm_v4_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[80:88])) + + // Field (5) 'Blob' + if cap(b.Blob) == 0 { + b.Blob = make([]byte, 0, len(buf[88:131160])) + } + b.Blob = append(b.Blob, buf[88:131160]...) + + // Field (6) 'KzgCommitment' + if cap(b.KzgCommitment) == 0 { + b.KzgCommitment = make([]byte, 0, len(buf[131160:131208])) + } + b.KzgCommitment = append(b.KzgCommitment, buf[131160:131208]...) + + // Field (7) 'KzgProof' + if cap(b.KzgProof) == 0 { + b.KzgProof = make([]byte, 0, len(buf[131208:131256])) + } + b.KzgProof = append(b.KzgProof, buf[131208:131256]...) + + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the BlobSidecar object +func (b *BlobSidecar) SizeSSZ() (size int) { + size = 131256 + return +} + +// HashTreeRoot ssz hashes the BlobSidecar object +func (b *BlobSidecar) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(b) +} + +// HashTreeRootWith ssz hashes the BlobSidecar object with a hasher +func (b *BlobSidecar) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'BlockRoot' + if size := len(b.BlockRoot); size != 32 { + err = ssz.ErrBytesLengthFn("--.BlockRoot", size, 32) + return + } + hh.PutBytes(b.BlockRoot) + + // Field (1) 'Index' + hh.PutUint64(b.Index) + + // Field (2) 'Slot' + hh.PutUint64(uint64(b.Slot)) + + // Field (3) 'BlockParentRoot' + if size := len(b.BlockParentRoot); size != 32 { + err = ssz.ErrBytesLengthFn("--.BlockParentRoot", size, 32) + return + } + hh.PutBytes(b.BlockParentRoot) + + // Field (4) 'ProposerIndex' + hh.PutUint64(uint64(b.ProposerIndex)) + + // Field (5) 'Blob' + if size := len(b.Blob); size != 131072 { + err = ssz.ErrBytesLengthFn("--.Blob", size, 131072) + return + } + hh.PutBytes(b.Blob) + + // Field (6) 'KzgCommitment' + if size := len(b.KzgCommitment); size != 48 { + err = ssz.ErrBytesLengthFn("--.KzgCommitment", size, 48) + return + } + hh.PutBytes(b.KzgCommitment) + + // Field (7) 'KzgProof' + if size := len(b.KzgProof); size != 48 { + err = ssz.ErrBytesLengthFn("--.KzgProof", size, 48) + return + } + hh.PutBytes(b.KzgProof) + + if ssz.EnableVectorizedHTR { + hh.MerkleizeVectorizedHTR(indx) + } else { + hh.Merkleize(indx) + } + return +} + // MarshalSSZ ssz marshals the SignedBlindedBlobSidecar object func (s *SignedBlindedBlobSidecar) MarshalSSZ() ([]byte, error) { return ssz.MarshalSSZ(s) diff --git a/proto/migration/v1alpha1_to_v2.go b/proto/migration/v1alpha1_to_v2.go index 7836298172..56456d394f 100644 --- a/proto/migration/v1alpha1_to_v2.go +++ b/proto/migration/v1alpha1_to_v2.go @@ -172,6 +172,23 @@ func V1Alpha1BeaconBlockDenebToV2(v1alpha1Block *ethpbalpha.BeaconBlockDeneb) (* return v2Block, nil } +// V1Alpha1BlobSidecarsToV2 converts an array of v1alpha1 blinded blob sidecars to its v2 equivalent. +func V1Alpha1BlobSidecarsToV2(v1alpha1Blobs []*ethpbalpha.BlobSidecar) ([]*ethpbv2.BlobSidecar, error) { + v2Blobs := make([]*ethpbv2.BlobSidecar, len(v1alpha1Blobs)) + for index, v1Blob := range v1alpha1Blobs { + marshaledBlob, err := proto.Marshal(v1Blob) + if err != nil { + return nil, errors.Wrap(err, "could not marshal blob sidecar") + } + v2Blob := ðpbv2.BlobSidecar{} + if err := proto.Unmarshal(marshaledBlob, v2Blob); err != nil { + return nil, errors.Wrap(err, "could not unmarshal blob sidecar") + } + v2Blobs[index] = v2Blob + } + return v2Blobs, nil +} + // V1Alpha1BlindedBlobSidecarsToV2 converts an array of v1alpha1 blinded blob sidecars to its v2 equivalent. func V1Alpha1BlindedBlobSidecarsToV2(v1alpha1Blobs []*ethpbalpha.BlindedBlobSidecar) ([]*ethpbv2.BlindedBlobSidecar, error) { v2Blobs := make([]*ethpbv2.BlindedBlobSidecar, len(v1alpha1Blobs)) @@ -182,7 +199,7 @@ func V1Alpha1BlindedBlobSidecarsToV2(v1alpha1Blobs []*ethpbalpha.BlindedBlobSide } v2Blob := ðpbv2.BlindedBlobSidecar{} if err := proto.Unmarshal(marshaledBlob, v2Blob); err != nil { - return nil, errors.Wrap(err, "could not unmarshal blobs idecar") + return nil, errors.Wrap(err, "could not unmarshal blob sidecar") } v2Blobs[index] = v2Blob } diff --git a/proto/migration/v1alpha1_to_v2_test.go b/proto/migration/v1alpha1_to_v2_test.go index f27ace324e..11c208c826 100644 --- a/proto/migration/v1alpha1_to_v2_test.go +++ b/proto/migration/v1alpha1_to_v2_test.go @@ -279,6 +279,17 @@ func Test_V1Alpha1BeaconBlockCapellaToV2Blinded(t *testing.T) { assert.DeepEqual(t, alphaRoot, v2Root) } +func Test_V1Alpha1BlobSidecarsToV2(t *testing.T) { + sidecar := util.HydrateBlobSidecar(ðpbalpha.BlobSidecar{}) + blobs := []*ethpbalpha.BlobSidecar{ + sidecar, + } + sidecars, err := V1Alpha1BlobSidecarsToV2(blobs) + require.NoError(t, err) + require.Equal(t, len(sidecars), len(blobs)) + assert.DeepEqual(t, sidecars[0].Blob, blobs[0].Blob) +} + func TestBeaconStateAltairToProto(t *testing.T) { source, err := util.NewBeaconStateAltair(util.FillRootsNaturalOptAltair, func(state *ethpbalpha.BeaconStateAltair) error { state.GenesisTime = 1 diff --git a/runtime/interop/genesis.go b/runtime/interop/genesis.go index a1213bd7da..1a4761c777 100644 --- a/runtime/interop/genesis.go +++ b/runtime/interop/genesis.go @@ -117,6 +117,7 @@ func GethTestnetGenesis(genesisTime uint64, cfg *clparams.BeaconChainConfig) *co } shanghaiTime := GethShanghaiTime(genesisTime, cfg) + cancunTime := GethCancunTime(genesisTime, cfg) cc := ¶ms.ChainConfig{ ChainID: big.NewInt(defaultTestChainId), HomesteadBlock: bigz, @@ -141,6 +142,7 @@ func GethTestnetGenesis(genesisTime uint64, cfg *clparams.BeaconChainConfig) *co Epoch: 20000, }, ShanghaiTime: shanghaiTime, + CancunTime: cancunTime, } da := defaultDepositContractAllocation(cfg.DepositContractAddress) ma := minerAllocation() diff --git a/testing/endtoend/components/beacon_node.go b/testing/endtoend/components/beacon_node.go index c1efbc86bc..910f3b2733 100644 --- a/testing/endtoend/components/beacon_node.go +++ b/testing/endtoend/components/beacon_node.go @@ -301,7 +301,7 @@ func (node *BeaconNode) Start(ctx context.Context) error { } }() cmd.Stderr = stderr - log.Infof("Starting beacon chain %d with flags: %s", index, strings.Join(args[2:], " ")) + log.Infof("Starting beacon chain %d with flags: %s", index, strings.Join(args, " ")) if err = cmd.Start(); err != nil { return fmt.Errorf("failed to start beacon node: %w", err) } diff --git a/testing/endtoend/endtoend_setup_test.go b/testing/endtoend/endtoend_setup_test.go index 248b30dd32..8afb161d80 100644 --- a/testing/endtoend/endtoend_setup_test.go +++ b/testing/endtoend/endtoend_setup_test.go @@ -19,9 +19,9 @@ func e2eMinimal(t *testing.T, v int, cfgo ...types.E2EConfigOpt) *testRunner { require.NoError(t, params.SetActive(types.StartAt(v, params.E2ETestConfig()))) require.NoError(t, e2eParams.Init(t, e2eParams.StandardBeaconCount)) - // Run for 12 epochs if not in long-running to confirm long-running has no issues. + // Run for 14 epochs if not in long-running to confirm long-running has no issues. var err error - epochsToRun := 12 + epochsToRun := 14 epochStr, longRunning := os.LookupEnv("E2E_EPOCHS") if longRunning { epochsToRun, err = strconv.Atoi(epochStr) @@ -56,6 +56,7 @@ func e2eMinimal(t *testing.T, v int, cfgo ...types.E2EConfigOpt) *testRunner { ev.AltairForkTransition, ev.BellatrixForkTransition, ev.CapellaForkTransition, + ev.DenebForkTransition, ev.APIMiddlewareVerifyIntegrity, ev.APIGatewayV1Alpha1VerifyIntegrity, ev.FinishedSyncing, @@ -132,6 +133,7 @@ func e2eMainnet(t *testing.T, usePrysmSh, useMultiClient bool, cfg *params.Beaco ev.AltairForkTransition, ev.BellatrixForkTransition, ev.CapellaForkTransition, + ev.DenebForkTransition, ev.APIMiddlewareVerifyIntegrity, ev.APIGatewayV1Alpha1VerifyIntegrity, ev.FinishedSyncing, @@ -188,6 +190,7 @@ func scenarioEvals() []types.Evaluator { ev.AltairForkTransition, ev.BellatrixForkTransition, ev.CapellaForkTransition, + ev.DenebForkTransition, ev.APIMiddlewareVerifyIntegrity, ev.APIGatewayV1Alpha1VerifyIntegrity, ev.FinishedSyncing, @@ -209,6 +212,7 @@ func scenarioEvalsMulti() []types.Evaluator { ev.AltairForkTransition, ev.BellatrixForkTransition, ev.CapellaForkTransition, + ev.DenebForkTransition, ev.APIMiddlewareVerifyIntegrity, ev.APIGatewayV1Alpha1VerifyIntegrity, ev.FinishedSyncing, diff --git a/testing/endtoend/evaluators/fork.go b/testing/endtoend/evaluators/fork.go index 54d4499be0..f4e0823e17 100644 --- a/testing/endtoend/evaluators/fork.go +++ b/testing/endtoend/evaluators/fork.go @@ -47,6 +47,12 @@ var CapellaForkTransition = types.Evaluator{ Evaluation: capellaForkOccurs, } +var DenebForkTransition = types.Evaluator{ + Name: "deneb_fork_transition_%d", + Policy: policies.OnEpoch(helpers.DenebE2eForkEpoch), + Evaluation: denebForkOccurs, +} + func altairForkOccurs(_ *types.EvaluationContext, conns ...*grpc.ClientConn) error { conn := conns[0] client := ethpb.NewBeaconNodeValidatorClient(conn) @@ -176,3 +182,46 @@ func capellaForkOccurs(_ *types.EvaluationContext, conns ...*grpc.ClientConn) er } return nil } + +func denebForkOccurs(_ *types.EvaluationContext, conns ...*grpc.ClientConn) error { + conn := conns[0] + client := ethpb.NewBeaconNodeValidatorClient(conn) + ctx, cancel := context.WithTimeout(context.Background(), streamDeadline) + defer cancel() + stream, err := client.StreamBlocksAltair(ctx, ðpb.StreamBlocksRequest{VerifiedOnly: true}) + if err != nil { + return errors.Wrap(err, "failed to get stream") + } + fSlot, err := slots.EpochStart(helpers.DenebE2eForkEpoch) + if err != nil { + return err + } + if ctx.Err() == context.Canceled { + return errors.New("context canceled prematurely") + } + res, err := stream.Recv() + if err != nil { + return err + } + if res == nil || res.Block == nil { + return errors.New("nil block returned by beacon node") + } + + if res.GetBlock() == nil { + return errors.New("nil block returned by beacon node") + } + if res.GetDenebBlock() == nil { + return errors.Errorf("non-capella block returned after the fork with type %T", res.Block) + } + blk, err := blocks.NewSignedBeaconBlock(res.GetDenebBlock()) + if err != nil { + return err + } + if err := blocks.BeaconBlockIsNil(blk); err != nil { + return err + } + if blk.Block().Slot() < fSlot { + return errors.Errorf("wanted a block at slot >= %d but received %d", fSlot, blk.Block().Slot()) + } + return nil +} diff --git a/testing/endtoend/evaluators/operations.go b/testing/endtoend/evaluators/operations.go index 3749f1d143..c28eda1654 100644 --- a/testing/endtoend/evaluators/operations.go +++ b/testing/endtoend/evaluators/operations.go @@ -502,6 +502,14 @@ func validatorsVoteWithTheMajority(ec *e2etypes.EvaluationContext, conns ...*grp b := blk.GetBlindedCapellaBlock().Block slot = b.Slot vote = b.Body.Eth1Data.BlockHash + case *ethpb.BeaconBlockContainer_DenebBlock: + b := blk.GetDenebBlock().Block + slot = b.Slot + vote = b.Body.Eth1Data.BlockHash + case *ethpb.BeaconBlockContainer_BlindedDenebBlock: + b := blk.GetBlindedDenebBlock().Block + slot = b.Slot + vote = b.Body.Eth1Data.BlockHash default: return errors.New("block neither phase0,altair or bellatrix") } diff --git a/testing/endtoend/evaluators/validator.go b/testing/endtoend/evaluators/validator.go index bab47d7eaa..588713dd16 100644 --- a/testing/endtoend/evaluators/validator.go +++ b/testing/endtoend/evaluators/validator.go @@ -290,6 +290,12 @@ func syncCompatibleBlockFromCtr(container *ethpb.BeaconBlockContainer) (interfac if container.GetBlindedCapellaBlock() != nil { return blocks.NewSignedBeaconBlock(container.GetBlindedCapellaBlock()) } + if container.GetDenebBlock() != nil { + return blocks.NewSignedBeaconBlock(container.GetDenebBlock()) + } + if container.GetBlindedDenebBlock() != nil { + return blocks.NewSignedBeaconBlock(container.GetBlindedDenebBlock()) + } return nil, errors.New("no supported block type in container") } diff --git a/testing/endtoend/helpers/helpers.go b/testing/endtoend/helpers/helpers.go index 66a397ec68..a7e2be4f29 100644 --- a/testing/endtoend/helpers/helpers.go +++ b/testing/endtoend/helpers/helpers.go @@ -40,6 +40,7 @@ const ( AltairE2EForkEpoch = params.AltairE2EForkEpoch BellatrixE2EForkEpoch = params.BellatrixE2EForkEpoch CapellaE2EForkEpoch = params.CapellaE2EForkEpoch + DenebE2eForkEpoch = params.DenebE2EForkEpoch ) // Graffiti is a list of sample graffiti strings. diff --git a/testing/util/blob.go b/testing/util/blob.go index 291aa25403..46dde40106 100644 --- a/testing/util/blob.go +++ b/testing/util/blob.go @@ -5,6 +5,27 @@ import ( ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1" ) +// HydrateBlobSidecar hydrates a blob sidecar with correct field length sizes +// to comply with SSZ marshalling and unmarshalling rules. +func HydrateBlobSidecar(b *ethpb.BlobSidecar) *ethpb.BlobSidecar { + if b.BlockRoot == nil { + b.BlockRoot = make([]byte, fieldparams.RootLength) + } + if b.BlockParentRoot == nil { + b.BlockParentRoot = make([]byte, fieldparams.RootLength) + } + if b.Blob == nil { + b.Blob = make([]byte, fieldparams.BlobLength) + } + if b.KzgCommitment == nil { + b.KzgCommitment = make([]byte, fieldparams.BLSPubkeyLength) + } + if b.KzgProof == nil { + b.KzgProof = make([]byte, fieldparams.BLSPubkeyLength) + } + return b +} + // HydrateSignedBlindedBlobSidecar hydrates a signed blinded blob sidecar with correct field length sizes // to comply with SSZ marshalling and unmarshalling rules. func HydrateSignedBlindedBlobSidecar(b *ethpb.SignedBlindedBlobSidecar) *ethpb.SignedBlindedBlobSidecar {