Compare commits

...

4 Commits

Author SHA1 Message Date
terence tsao
94263441a5 Publish and save blobs 2024-08-22 08:18:11 -07:00
Preston Van Loon
2fa3547644 Update spectests to v1.5.0-alpha.5. Copied from #14352 (#14368) 2024-08-22 14:03:48 +00:00
Rupam Dey
7c213ce161 feat: implement PayloadProof function (#14356)
* feat: implement function `PayloadProof` to calculate proof of execution payload

* remove comments

* feat: implement function to compute field roots of

* feat: implement function to compute `BeaconBlock` field roots and add tests

* fix dependencies

* check if interface implements the assserted type

* fix: lint

* replace `ok != true` with `!ok`

* remove unused parameter from `PayloadProof`

* remove test and move `PayloadProof` to `blocks/proofs.go`

* remove `PayloadProof` from `fieldtrie`

* replace `fieldtrie.ProofFromMerkleLayers` with `trie.ProofFromMerkleLayers`

* Update container/trie/sparse_merkle.go

* update dependencies

---------

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
Co-authored-by: Radosław Kapka <radoslaw.kapka@gmail.com>
2024-08-21 16:04:35 +00:00
Radosław Kapka
ed3d7d49ec Update block publishing Beacon APIs to Electra (#14361)
* Update block publishing Beacon APIs to Electra

* linter
2024-08-20 16:57:08 +00:00
19 changed files with 1153 additions and 83 deletions

View File

@@ -227,7 +227,7 @@ filegroup(
url = "https://github.com/ethereum/EIPs/archive/5480440fe51742ed23342b68cf106cefd427e39d.tar.gz",
)
consensus_spec_version = "v1.5.0-alpha.4"
consensus_spec_version = "v1.5.0-alpha.5"
bls_test_version = "v0.1.1"
@@ -243,7 +243,7 @@ filegroup(
visibility = ["//visibility:public"],
)
""",
integrity = "sha256-sSw6c9IR/ZiWjyk1cbfVGC/aUkId4r7+eSl3haWsq0E=",
integrity = "sha256-R9vG5HEL5eGMOAmbkKfJ2jfelNqL5V0xBUPiXOiGM6U=",
url = "https://github.com/ethereum/consensus-spec-tests/releases/download/%s/general.tar.gz" % consensus_spec_version,
)
@@ -259,7 +259,7 @@ filegroup(
visibility = ["//visibility:public"],
)
""",
integrity = "sha256-OGlKhbA6TjTP0p1ojXVCJPzLEHJzewKkhAa+PQggoiU=",
integrity = "sha256-AEIiEOlf1XuxoRMCsN+kgJMo4LrS05+biTA1p/7Ro00=",
url = "https://github.com/ethereum/consensus-spec-tests/releases/download/%s/minimal.tar.gz" % consensus_spec_version,
)
@@ -275,7 +275,7 @@ filegroup(
visibility = ["//visibility:public"],
)
""",
integrity = "sha256-ah2Gj4ci5hw5vQgpUWkNjEQutoBCepg5jcpTi0DKVB0=",
integrity = "sha256-LH/Xr20yrJRYnbpjRGupMWTIOWt3cpxZJWXgThwVDsk=",
url = "https://github.com/ethereum/consensus-spec-tests/releases/download/%s/mainnet.tar.gz" % consensus_spec_version,
)
@@ -290,7 +290,7 @@ filegroup(
visibility = ["//visibility:public"],
)
""",
integrity = "sha256-I+llAsIF6lPP8RUtZ2DFsJqtCs4UPh+st3hFs12FWpY=",
integrity = "sha256-mlytz4MPjKh0DwV7FMiAtnRbJw9B6o78/x66/vmnYc8=",
strip_prefix = "consensus-specs-" + consensus_spec_version[1:],
url = "https://github.com/ethereum/consensus-specs/archive/refs/tags/%s.tar.gz" % consensus_spec_version,
)

View File

@@ -465,6 +465,7 @@ func (s *Service) beaconEndpoints(
OperationNotifier: s.cfg.OperationNotifier,
Broadcaster: s.cfg.Broadcaster,
BlockReceiver: s.cfg.BlockReceiver,
BlobReceiver: s.cfg.BlobReceiver,
StateGenService: s.cfg.StateGen,
Stater: stater,
Blocker: blocker,

View File

@@ -286,7 +286,7 @@ func (s *Server) PublishBlindedBlockV2(w http.ResponseWriter, r *http.Request) {
}
}
func (s *Server) publishBlindedBlockSSZ(ctx context.Context, w http.ResponseWriter, r *http.Request, versionRequired bool) {
func (s *Server) publishBlindedBlockSSZ(ctx context.Context, w http.ResponseWriter, r *http.Request, versionRequired bool) { // nolint:gocognit
body, err := io.ReadAll(r.Body)
if err != nil {
httputil.HandleError(w, "Could not read request body: "+err.Error(), http.StatusInternalServerError)
@@ -297,6 +297,29 @@ func (s *Server) publishBlindedBlockSSZ(ctx context.Context, w http.ResponseWrit
httputil.HandleError(w, api.VersionHeader+" header is required", http.StatusBadRequest)
}
electraBlock := &eth.SignedBlindedBeaconBlockElectra{}
if err = electraBlock.UnmarshalSSZ(body); err == nil {
genericBlock := &eth.GenericSignedBeaconBlock{
Block: &eth.GenericSignedBeaconBlock_BlindedElectra{
BlindedElectra: electraBlock,
},
}
if err = s.validateBroadcast(ctx, r, genericBlock); err != nil {
httputil.HandleError(w, err.Error(), http.StatusBadRequest)
return
}
s.proposeBlock(ctx, w, genericBlock)
return
}
if versionHeader == version.String(version.Electra) {
httputil.HandleError(
w,
fmt.Sprintf("Could not decode request body into %s consensus block: %v", version.String(version.Electra), err.Error()),
http.StatusBadRequest,
)
return
}
denebBlock := &eth.SignedBlindedBeaconBlockDeneb{}
if err = denebBlock.UnmarshalSSZ(body); err == nil {
genericBlock := &eth.GenericSignedBeaconBlock{
@@ -415,7 +438,7 @@ func (s *Server) publishBlindedBlockSSZ(ctx context.Context, w http.ResponseWrit
httputil.HandleError(w, "Body does not represent a valid block type", http.StatusBadRequest)
}
func (s *Server) publishBlindedBlock(ctx context.Context, w http.ResponseWriter, r *http.Request, versionRequired bool) {
func (s *Server) publishBlindedBlock(ctx context.Context, w http.ResponseWriter, r *http.Request, versionRequired bool) { // nolint:gocognit
body, err := io.ReadAll(r.Body)
if err != nil {
httputil.HandleError(w, "Could not read request body", http.StatusInternalServerError)
@@ -428,6 +451,27 @@ func (s *Server) publishBlindedBlock(ctx context.Context, w http.ResponseWriter,
var consensusBlock *eth.GenericSignedBeaconBlock
var electraBlock *structs.SignedBlindedBeaconBlockElectra
if err = unmarshalStrict(body, &electraBlock); err == nil {
consensusBlock, err = electraBlock.ToGeneric()
if err == nil {
if err = s.validateBroadcast(ctx, r, consensusBlock); err != nil {
httputil.HandleError(w, err.Error(), http.StatusBadRequest)
return
}
s.proposeBlock(ctx, w, consensusBlock)
return
}
}
if versionHeader == version.String(version.Electra) {
httputil.HandleError(
w,
fmt.Sprintf("Could not decode request body into %s consensus block: %v", version.String(version.Electra), err.Error()),
http.StatusBadRequest,
)
return
}
var denebBlock *structs.SignedBlindedBeaconBlockDeneb
if err = unmarshalStrict(body, &denebBlock); err == nil {
consensusBlock, err = denebBlock.ToGeneric()
@@ -579,7 +623,7 @@ func (s *Server) PublishBlockV2(w http.ResponseWriter, r *http.Request) {
}
}
func (s *Server) publishBlockSSZ(ctx context.Context, w http.ResponseWriter, r *http.Request, versionRequired bool) {
func (s *Server) publishBlockSSZ(ctx context.Context, w http.ResponseWriter, r *http.Request, versionRequired bool) { // nolint:gocognit
body, err := io.ReadAll(r.Body)
if err != nil {
httputil.HandleError(w, "Could not read request body", http.StatusInternalServerError)
@@ -591,6 +635,39 @@ func (s *Server) publishBlockSSZ(ctx context.Context, w http.ResponseWriter, r *
return
}
electraBlock := &eth.SignedBeaconBlockContentsElectra{}
if err = electraBlock.UnmarshalSSZ(body); err == nil {
genericBlock := &eth.GenericSignedBeaconBlock{
Block: &eth.GenericSignedBeaconBlock_Electra{
Electra: electraBlock,
},
}
if err = s.validateBroadcast(ctx, r, genericBlock); err != nil {
if errors.Is(err, errEquivocatedBlock) {
b, err := blocks.NewSignedBeaconBlock(genericBlock)
if err != nil {
httputil.HandleError(w, err.Error(), http.StatusBadRequest)
return
}
if err := s.broadcastSeenBlockSidecars(ctx, b, genericBlock.GetElectra().Blobs, genericBlock.GetElectra().KzgProofs); err != nil {
log.WithError(err).Error("Failed to broadcast blob sidecars")
}
}
httputil.HandleError(w, err.Error(), http.StatusBadRequest)
return
}
s.proposeBlock(ctx, w, genericBlock)
return
}
if versionHeader == version.String(version.Electra) {
httputil.HandleError(
w,
fmt.Sprintf("Could not decode request body into %s consensus block: %v", version.String(version.Electra), err.Error()),
http.StatusBadRequest,
)
return
}
denebBlock := &eth.SignedBeaconBlockContentsDeneb{}
if err = denebBlock.UnmarshalSSZ(body); err == nil {
genericBlock := &eth.GenericSignedBeaconBlock{
@@ -719,7 +796,7 @@ func (s *Server) publishBlockSSZ(ctx context.Context, w http.ResponseWriter, r *
httputil.HandleError(w, "Body does not represent a valid block type", http.StatusBadRequest)
}
func (s *Server) publishBlock(ctx context.Context, w http.ResponseWriter, r *http.Request, versionRequired bool) {
func (s *Server) publishBlock(ctx context.Context, w http.ResponseWriter, r *http.Request, versionRequired bool) { // nolint:gocognit
body, err := io.ReadAll(r.Body)
if err != nil {
httputil.HandleError(w, "Could not read request body", http.StatusInternalServerError)
@@ -733,6 +810,37 @@ func (s *Server) publishBlock(ctx context.Context, w http.ResponseWriter, r *htt
var consensusBlock *eth.GenericSignedBeaconBlock
var electraBlockContents *structs.SignedBeaconBlockContentsElectra
if err = unmarshalStrict(body, &electraBlockContents); err == nil {
consensusBlock, err = electraBlockContents.ToGeneric()
if err == nil {
if err = s.validateBroadcast(ctx, r, consensusBlock); err != nil {
if errors.Is(err, errEquivocatedBlock) {
b, err := blocks.NewSignedBeaconBlock(consensusBlock)
if err != nil {
httputil.HandleError(w, err.Error(), http.StatusBadRequest)
return
}
if err := s.broadcastSeenBlockSidecars(ctx, b, consensusBlock.GetElectra().Blobs, consensusBlock.GetElectra().KzgProofs); err != nil {
log.WithError(err).Error("Failed to broadcast blob sidecars")
}
}
httputil.HandleError(w, err.Error(), http.StatusBadRequest)
return
}
s.proposeBlock(ctx, w, consensusBlock)
return
}
}
if versionHeader == version.String(version.Electra) {
httputil.HandleError(
w,
fmt.Sprintf("Could not decode request body into %s consensus block: %v", version.String(version.Electra), err.Error()),
http.StatusBadRequest,
)
return
}
var denebBlockContents *structs.SignedBeaconBlockContentsDeneb
if err = unmarshalStrict(body, &denebBlockContents); err == nil {
consensusBlock, err = denebBlockContents.ToGeneric()
@@ -1476,3 +1584,41 @@ func (s *Server) broadcastSeenBlockSidecars(
}
return nil
}
func (s *Server) PublishBlobs(w http.ResponseWriter, r *http.Request) {
ctx, span := trace.StartSpan(r.Context(), "beacon.PublishBlobs")
defer span.End()
if shared.IsSyncing(r.Context(), w, s.SyncChecker, s.HeadFetcher, s.TimeFetcher, s.OptimisticModeFetcher) {
return
}
body, err := io.ReadAll(r.Body)
if err != nil {
httputil.HandleError(w, "Could not read request body", http.StatusInternalServerError)
return
}
blobSidecars := &eth.BlobSidecars{}
if err := blobSidecars.UnmarshalSSZ(body); err != nil {
httputil.HandleError(w, "Could not unmarshal blob sidecars", http.StatusBadRequest)
return
}
for _, blobSidecar := range blobSidecars.Sidecars {
readOnlySc, err := blocks.NewROBlobWithRoot(blobSidecar, [32]byte{}) // TODO: replace [32]byte{} with beacon root
if err != nil {
http.Error(w, "Could not create read-only blob", http.StatusInternalServerError)
return
}
verifiedBlob := blocks.NewVerifiedROBlob(readOnlySc)
if err := s.BlobReceiver.ReceiveBlob(ctx, verifiedBlob); err != nil {
http.Error(w, "Could not receive blob", http.StatusInternalServerError)
return
}
if err := s.Broadcaster.BroadcastBlob(ctx, blobSidecar.Index, blobSidecar); err != nil {
log.WithError(err).Error("Failed to broadcast blob")
}
}
}

View File

@@ -1071,6 +1071,29 @@ func TestPublishBlock(t *testing.T) {
server.PublishBlock(writer, request)
assert.Equal(t, http.StatusOK, writer.Code)
})
t.Run("Electra", func(t *testing.T) {
v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl)
v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool {
block, ok := req.Block.(*eth.GenericSignedBeaconBlock_Electra)
converted, err := structs.SignedBeaconBlockContentsElectraFromConsensus(block.Electra)
require.NoError(t, err)
var signedblock *structs.SignedBeaconBlockContentsElectra
err = json.Unmarshal([]byte(rpctesting.ElectraBlockContents), &signedblock)
require.NoError(t, err)
require.DeepEqual(t, converted, signedblock)
return ok
}))
server := &Server{
V1Alpha1ValidatorServer: v1alpha1Server,
SyncChecker: &mockSync.Sync{IsSyncing: false},
}
request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(rpctesting.ElectraBlockContents)))
request.Header.Set(api.VersionHeader, version.String(version.Electra))
writer := httptest.NewRecorder()
writer.Body = &bytes.Buffer{}
server.PublishBlock(writer, request)
assert.Equal(t, http.StatusOK, writer.Code)
})
t.Run("invalid block", func(t *testing.T) {
server := &Server{
SyncChecker: &mockSync.Sync{IsSyncing: false},
@@ -1254,6 +1277,32 @@ func TestPublishBlockSSZ(t *testing.T) {
server.PublishBlock(writer, request)
assert.Equal(t, http.StatusOK, writer.Code)
})
t.Run("Electra", func(t *testing.T) {
v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl)
v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool {
_, ok := req.Block.(*eth.GenericSignedBeaconBlock_Electra)
return ok
}))
server := &Server{
V1Alpha1ValidatorServer: v1alpha1Server,
SyncChecker: &mockSync.Sync{IsSyncing: false},
}
var blk structs.SignedBeaconBlockContentsElectra
err := json.Unmarshal([]byte(rpctesting.ElectraBlockContents), &blk)
require.NoError(t, err)
genericBlock, err := blk.ToGeneric()
require.NoError(t, err)
ssz, err := genericBlock.GetElectra().MarshalSSZ()
require.NoError(t, err)
request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader(ssz))
request.Header.Set("Content-Type", api.OctetStreamMediaType)
request.Header.Set(api.VersionHeader, version.String(version.Electra))
writer := httptest.NewRecorder()
writer.Body = &bytes.Buffer{}
server.PublishBlock(writer, request)
assert.Equal(t, http.StatusOK, writer.Code)
})
t.Run("invalid block", func(t *testing.T) {
server := &Server{
SyncChecker: &mockSync.Sync{IsSyncing: false},
@@ -1433,6 +1482,30 @@ func TestPublishBlindedBlock(t *testing.T) {
server.PublishBlindedBlock(writer, request)
assert.Equal(t, http.StatusOK, writer.Code)
})
t.Run("Blinded Electra", func(t *testing.T) {
v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl)
v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool {
block, ok := req.Block.(*eth.GenericSignedBeaconBlock_BlindedElectra)
converted, err := structs.BlindedBeaconBlockElectraFromConsensus(block.BlindedElectra.Message)
require.NoError(t, err)
var signedblock *structs.SignedBlindedBeaconBlockElectra
err = json.Unmarshal([]byte(rpctesting.BlindedElectraBlock), &signedblock)
require.NoError(t, err)
require.DeepEqual(t, converted, signedblock.Message)
return ok
}))
server := &Server{
V1Alpha1ValidatorServer: v1alpha1Server,
SyncChecker: &mockSync.Sync{IsSyncing: false},
}
request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(rpctesting.BlindedElectraBlock)))
request.Header.Set(api.VersionHeader, version.String(version.Electra))
writer := httptest.NewRecorder()
writer.Body = &bytes.Buffer{}
server.PublishBlindedBlock(writer, request)
assert.Equal(t, http.StatusOK, writer.Code)
})
t.Run("invalid block", func(t *testing.T) {
server := &Server{
SyncChecker: &mockSync.Sync{IsSyncing: false},
@@ -1617,6 +1690,32 @@ func TestPublishBlindedBlockSSZ(t *testing.T) {
server.PublishBlindedBlock(writer, request)
assert.Equal(t, http.StatusOK, writer.Code)
})
t.Run("Electra", func(t *testing.T) {
v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl)
v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool {
_, ok := req.Block.(*eth.GenericSignedBeaconBlock_BlindedElectra)
return ok
}))
server := &Server{
V1Alpha1ValidatorServer: v1alpha1Server,
SyncChecker: &mockSync.Sync{IsSyncing: false},
}
var blk structs.SignedBlindedBeaconBlockElectra
err := json.Unmarshal([]byte(rpctesting.BlindedElectraBlock), &blk)
require.NoError(t, err)
genericBlock, err := blk.ToGeneric()
require.NoError(t, err)
ssz, err := genericBlock.GetBlindedElectra().MarshalSSZ()
require.NoError(t, err)
request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader(ssz))
request.Header.Set("Content-Type", api.OctetStreamMediaType)
request.Header.Set(api.VersionHeader, version.String(version.Electra))
writer := httptest.NewRecorder()
writer.Body = &bytes.Buffer{}
server.PublishBlindedBlock(writer, request)
assert.Equal(t, http.StatusOK, writer.Code)
})
t.Run("invalid block", func(t *testing.T) {
server := &Server{
SyncChecker: &mockSync.Sync{IsSyncing: false},
@@ -1788,6 +1887,30 @@ func TestPublishBlockV2(t *testing.T) {
server.PublishBlockV2(writer, request)
assert.Equal(t, http.StatusOK, writer.Code)
})
t.Run("Electra", func(t *testing.T) {
v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl)
v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool {
block, ok := req.Block.(*eth.GenericSignedBeaconBlock_Electra)
converted, err := structs.SignedBeaconBlockContentsElectraFromConsensus(block.Electra)
require.NoError(t, err)
var signedblock *structs.SignedBeaconBlockContentsElectra
err = json.Unmarshal([]byte(rpctesting.ElectraBlockContents), &signedblock)
require.NoError(t, err)
require.DeepEqual(t, converted, signedblock)
return ok
}))
server := &Server{
V1Alpha1ValidatorServer: v1alpha1Server,
SyncChecker: &mockSync.Sync{IsSyncing: false},
}
request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(rpctesting.ElectraBlockContents)))
request.Header.Set(api.VersionHeader, version.String(version.Electra))
writer := httptest.NewRecorder()
writer.Body = &bytes.Buffer{}
server.PublishBlockV2(writer, request)
assert.Equal(t, http.StatusOK, writer.Code)
})
t.Run("invalid block", func(t *testing.T) {
server := &Server{
SyncChecker: &mockSync.Sync{IsSyncing: false},
@@ -1984,6 +2107,32 @@ func TestPublishBlockV2SSZ(t *testing.T) {
server.PublishBlockV2(writer, request)
assert.Equal(t, http.StatusOK, writer.Code)
})
t.Run("Electra", func(t *testing.T) {
v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl)
v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool {
_, ok := req.Block.(*eth.GenericSignedBeaconBlock_Electra)
return ok
}))
server := &Server{
V1Alpha1ValidatorServer: v1alpha1Server,
SyncChecker: &mockSync.Sync{IsSyncing: false},
}
var blk structs.SignedBeaconBlockContentsElectra
err := json.Unmarshal([]byte(rpctesting.ElectraBlockContents), &blk)
require.NoError(t, err)
genericBlock, err := blk.ToGeneric()
require.NoError(t, err)
ssz, err := genericBlock.GetElectra().MarshalSSZ()
require.NoError(t, err)
request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader(ssz))
request.Header.Set("Content-Type", api.OctetStreamMediaType)
request.Header.Set(api.VersionHeader, version.String(version.Electra))
writer := httptest.NewRecorder()
writer.Body = &bytes.Buffer{}
server.PublishBlockV2(writer, request)
assert.Equal(t, http.StatusOK, writer.Code)
})
t.Run("invalid block", func(t *testing.T) {
server := &Server{
SyncChecker: &mockSync.Sync{IsSyncing: false},
@@ -2176,6 +2325,30 @@ func TestPublishBlindedBlockV2(t *testing.T) {
server.PublishBlindedBlockV2(writer, request)
assert.Equal(t, http.StatusOK, writer.Code)
})
t.Run("Blinded Electra", func(t *testing.T) {
v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl)
v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool {
block, ok := req.Block.(*eth.GenericSignedBeaconBlock_BlindedElectra)
converted, err := structs.BlindedBeaconBlockElectraFromConsensus(block.BlindedElectra.Message)
require.NoError(t, err)
var signedblock *structs.SignedBlindedBeaconBlockElectra
err = json.Unmarshal([]byte(rpctesting.BlindedElectraBlock), &signedblock)
require.NoError(t, err)
require.DeepEqual(t, converted, signedblock.Message)
return ok
}))
server := &Server{
V1Alpha1ValidatorServer: v1alpha1Server,
SyncChecker: &mockSync.Sync{IsSyncing: false},
}
request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(rpctesting.BlindedElectraBlock)))
request.Header.Set(api.VersionHeader, version.String(version.Electra))
writer := httptest.NewRecorder()
writer.Body = &bytes.Buffer{}
server.PublishBlindedBlockV2(writer, request)
assert.Equal(t, http.StatusOK, writer.Code)
})
t.Run("invalid block", func(t *testing.T) {
server := &Server{
SyncChecker: &mockSync.Sync{IsSyncing: false},
@@ -2372,6 +2545,32 @@ func TestPublishBlindedBlockV2SSZ(t *testing.T) {
server.PublishBlindedBlock(writer, request)
assert.Equal(t, http.StatusOK, writer.Code)
})
t.Run("Electra", func(t *testing.T) {
v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl)
v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool {
_, ok := req.Block.(*eth.GenericSignedBeaconBlock_BlindedElectra)
return ok
}))
server := &Server{
V1Alpha1ValidatorServer: v1alpha1Server,
SyncChecker: &mockSync.Sync{IsSyncing: false},
}
var blk structs.SignedBlindedBeaconBlockElectra
err := json.Unmarshal([]byte(rpctesting.BlindedElectraBlock), &blk)
require.NoError(t, err)
genericBlock, err := blk.ToGeneric()
require.NoError(t, err)
ssz, err := genericBlock.GetBlindedElectra().MarshalSSZ()
require.NoError(t, err)
request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader(ssz))
request.Header.Set("Content-Type", api.OctetStreamMediaType)
request.Header.Set(api.VersionHeader, version.String(version.Electra))
writer := httptest.NewRecorder()
writer.Body = &bytes.Buffer{}
server.PublishBlindedBlock(writer, request)
assert.Equal(t, http.StatusOK, writer.Code)
})
t.Run("invalid block", func(t *testing.T) {
server := &Server{
SyncChecker: &mockSync.Sync{IsSyncing: false},

View File

@@ -48,4 +48,5 @@ type Server struct {
BLSChangesPool blstoexec.PoolManager
ForkchoiceFetcher blockchain.ForkchoiceFetcher
CoreService *core.Service
BlobReceiver blockchain.BlobReceiver
}

View File

@@ -488,7 +488,7 @@ func TestGetSpec(t *testing.T) {
case "MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT":
assert.Equal(t, "256000000000", v)
case "DATA_COLUMN_SIDECAR_SUBNET_COUNT":
assert.Equal(t, "32", v)
assert.Equal(t, "128", v)
case "MAX_REQUEST_DATA_COLUMN_SIDECARS":
assert.Equal(t, "16384", v)
case "MIN_SLASHING_PENALTY_QUOTIENT_ELECTRA":

View File

@@ -3,7 +3,11 @@ load("@prysm//tools/go:def.bzl", "go_library")
go_library(
name = "go_default_library",
testonly = True,
srcs = ["json.go"],
srcs = [
"json.go",
"json_mainnet.go",
"json_minimal.go", # keep
],
importpath = "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/eth/shared/testing",
visibility = ["//visibility:public"],
)

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,5 @@
//go:build !minimal
package testing
const attestationCommitteeBits = "0x0100000000000000"

View File

@@ -0,0 +1,5 @@
//go:build minimal
package testing
const attestationCommitteeBits = "0x01"

View File

@@ -14,21 +14,6 @@ import (
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
)
// ProofFromMerkleLayers creates a proof starting at the leaf index of the state Merkle layers.
func ProofFromMerkleLayers(layers [][][]byte, startingLeafIndex int) [][]byte {
// The merkle tree structure looks as follows:
// [[r1, r2, r3, r4], [parent1, parent2], [root]]
proof := make([][]byte, 0)
currentIndex := startingLeafIndex
for i := 0; i < len(layers)-1; i++ {
neighborIdx := currentIndex ^ 1
neighbor := layers[i][neighborIdx]
proof = append(proof, neighbor)
currentIndex = currentIndex / 2
}
return proof
}
func (f *FieldTrie) validateIndices(idxs []uint64) error {
length := f.length
if f.dataType == types.CompressedArray {

View File

@@ -67,6 +67,7 @@ go_library(
"//consensus-types/primitives:go_default_library",
"//container/multi-value-slice:go_default_library",
"//container/slice:go_default_library",
"//container/trie:go_default_library",
"//crypto/bls:go_default_library",
"//crypto/hash:go_default_library",
"//encoding/bytesutil:go_default_library",

View File

@@ -4,8 +4,8 @@ import (
"context"
"encoding/binary"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state/fieldtrie"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native/types"
"github.com/prysmaticlabs/prysm/v5/container/trie"
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/v5/runtime/version"
)
@@ -56,7 +56,7 @@ func (b *BeaconState) CurrentSyncCommitteeProof(ctx context.Context) ([][]byte,
if err := b.recomputeDirtyFields(ctx); err != nil {
return nil, err
}
return fieldtrie.ProofFromMerkleLayers(b.merkleLayers, types.CurrentSyncCommittee.RealPosition()), nil
return trie.ProofFromMerkleLayers(b.merkleLayers, types.CurrentSyncCommittee.RealPosition()), nil
}
// NextSyncCommitteeProof from the state's Merkle trie representation.
@@ -74,7 +74,7 @@ func (b *BeaconState) NextSyncCommitteeProof(ctx context.Context) ([][]byte, err
if err := b.recomputeDirtyFields(ctx); err != nil {
return nil, err
}
return fieldtrie.ProofFromMerkleLayers(b.merkleLayers, types.NextSyncCommittee.RealPosition()), nil
return trie.ProofFromMerkleLayers(b.merkleLayers, types.NextSyncCommittee.RealPosition()), nil
}
// FinalizedRootProof crafts a Merkle proof for the finalized root
@@ -102,7 +102,7 @@ func (b *BeaconState) FinalizedRootProof(ctx context.Context) ([][]byte, error)
epochRoot := bytesutil.ToBytes32(epochBuf)
proof := make([][]byte, 0)
proof = append(proof, epochRoot[:])
branch := fieldtrie.ProofFromMerkleLayers(b.merkleLayers, types.FinalizedCheckpoint.RealPosition())
branch := trie.ProofFromMerkleLayers(b.merkleLayers, types.FinalizedCheckpoint.RealPosition())
proof = append(proof, branch...)
return proof, nil
}

View File

@@ -276,7 +276,7 @@ var mainnetBeaconConfig = &BeaconChainConfig{
// Values related to electra
MaxRequestDataColumnSidecars: 16384,
DataColumnSidecarSubnetCount: 32,
DataColumnSidecarSubnetCount: 128,
MinPerEpochChurnLimitElectra: 128_000_000_000,
MaxPerEpochActivationExitChurnLimit: 256_000_000_000,
MaxEffectiveBalanceElectra: 2048_000_000_000,
@@ -293,6 +293,10 @@ var mainnetBeaconConfig = &BeaconChainConfig{
MaxDepositRequestsPerPayload: 8192, // 2**13 (= 8192)
UnsetDepositRequestsStartIndex: math.MaxUint64,
// PeerDAS
NumberOfColumns: 128,
MaxCellsInExtendedMatrix: 768,
// Values related to networking parameters.
GossipMaxSize: 10 * 1 << 20, // 10 MiB
MaxChunkSize: 10 * 1 << 20, // 10 MiB
@@ -310,10 +314,6 @@ var mainnetBeaconConfig = &BeaconChainConfig{
AttestationSubnetPrefixBits: 6,
SubnetsPerNode: 2,
NodeIdBits: 256,
// PeerDAS
NumberOfColumns: 128,
MaxCellsInExtendedMatrix: 768,
}
// MainnetTestConfig provides a version of the mainnet config that has a different name

View File

@@ -18,6 +18,7 @@ go_library(
importpath = "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks",
visibility = ["//visibility:public"],
deps = [
"//beacon-chain/state/stateutil:go_default_library",
"//config/fieldparams:go_default_library",
"//config/params:go_default_library",
"//consensus-types:go_default_library",

View File

@@ -3,15 +3,23 @@ package blocks
import (
"context"
"encoding/binary"
"errors"
"fmt"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state/stateutil"
"github.com/prysmaticlabs/prysm/v5/config/params"
"github.com/prysmaticlabs/prysm/v5/container/trie"
"github.com/prysmaticlabs/prysm/v5/crypto/hash/htr"
"github.com/prysmaticlabs/prysm/v5/encoding/ssz"
"github.com/prysmaticlabs/prysm/v5/runtime/version"
"go.opencensus.io/trace"
)
const (
payloadFieldIndex = 9
bodyFieldIndex = 4
)
func ComputeBlockBodyFieldRoots(ctx context.Context, blockBody *BeaconBlockBody) ([][]byte, error) {
_, span := trace.StartSpan(ctx, "blocks.ComputeBlockBodyFieldRoots")
defer span.End()
@@ -172,3 +180,68 @@ func ComputeBlockBodyFieldRoots(ctx context.Context, blockBody *BeaconBlockBody)
return fieldRoots, nil
}
func ComputeBlockFieldRoots(ctx context.Context, block *BeaconBlock) ([][]byte, error) {
_, span := trace.StartSpan(ctx, "blocks.ComputeBlockFieldRoots")
defer span.End()
if block == nil {
return nil, errNilBlock
}
fieldRoots := make([][]byte, 5)
for i := range fieldRoots {
fieldRoots[i] = make([]byte, 32)
}
// Slot
slotRoot := ssz.Uint64Root(uint64(block.slot))
copy(fieldRoots[0], slotRoot[:])
// Proposer Index
proposerRoot := ssz.Uint64Root(uint64(block.proposerIndex))
copy(fieldRoots[1], proposerRoot[:])
// Parent Root
copy(fieldRoots[2], block.parentRoot[:])
// State Root
copy(fieldRoots[3], block.stateRoot[:])
// block body Root
blockBodyRoot, err := block.body.HashTreeRoot()
if err != nil {
return nil, err
}
copy(fieldRoots[4], blockBodyRoot[:])
return fieldRoots, nil
}
func PayloadProof(ctx context.Context, block *BeaconBlock) ([][]byte, error) {
i := block.Body()
blockBody, ok := i.(*BeaconBlockBody)
if !ok {
return nil, errors.New("failed to cast block body")
}
blockBodyFieldRoots, err := ComputeBlockBodyFieldRoots(ctx, blockBody)
if err != nil {
return nil, err
}
blockBodyFieldRootsTrie := stateutil.Merkleize(blockBodyFieldRoots)
blockBodyProof := trie.ProofFromMerkleLayers(blockBodyFieldRootsTrie, payloadFieldIndex)
beaconBlockFieldRoots, err := ComputeBlockFieldRoots(ctx, block)
if err != nil {
return nil, err
}
beaconBlockFieldRootsTrie := stateutil.Merkleize(beaconBlockFieldRoots)
beaconBlockProof := trie.ProofFromMerkleLayers(beaconBlockFieldRootsTrie, bodyFieldIndex)
finalProof := append(blockBodyProof, beaconBlockProof...)
return finalProof, nil
}

View File

@@ -259,3 +259,18 @@ func (m *SparseMerkleTrie) NumOfItems() int {
}
return len(m.originalItems)
}
// ProofFromMerkleLayers creates a proof starting at the leaf index of the merkle layers.
func ProofFromMerkleLayers(layers [][][]byte, startingLeafIndex int) [][]byte {
// The merkle tree structure looks as follows:
// [[r1, r2, r3, r4], [parent1, parent2], [root]]
proof := make([][]byte, 0)
currentIndex := startingLeafIndex
for i := 0; i < len(layers)-1; i++ {
neighborIdx := currentIndex ^ 1
neighbor := layers[i][neighborIdx]
proof = append(proof, neighbor)
currentIndex = currentIndex / 2
}
return proof
}

View File

@@ -149,6 +149,7 @@ ssz_electra_objs = [
"PendingConsolidation",
"PendingPartialWithdrawal",
"SignedAggregateAttestationAndProofElectra",
"SignedBeaconBlockContentsElectra",
"SignedBeaconBlockElectra",
"SignedBlindedBeaconBlockElectra",
"SignedConsolidation",
@@ -156,90 +157,89 @@ ssz_electra_objs = [
ssz_gen_marshal(
name = "ssz_generated_phase0",
go_proto = ":go_proto",
out = "phase0.ssz.go",
go_proto = ":go_proto",
includes = [
"//consensus-types/primitives:go_default_library",
"//proto/engine/v1:go_default_library",
"//math:go_default_library",
"//proto/engine/v1:go_default_library",
],
objs = ssz_phase0_objs,
)
ssz_gen_marshal(
name = "ssz_generated_altair",
go_proto = ":go_proto",
out = "altair.ssz.go",
exclude_objs = ssz_phase0_objs,
go_proto = ":go_proto",
includes = [
"//consensus-types/primitives:go_default_library",
"//proto/engine/v1:go_default_library",
"//math:go_default_library",
"//proto/engine/v1:go_default_library",
],
objs = ssz_altair_objs,
exclude_objs = ssz_phase0_objs,
)
ssz_gen_marshal(
name = "ssz_generated_bellatrix",
go_proto = ":go_proto",
out = "bellatrix.ssz.go",
exclude_objs = ssz_phase0_objs + ssz_altair_objs,
go_proto = ":go_proto",
includes = [
"//consensus-types/primitives:go_default_library",
"//proto/engine/v1:go_default_library",
"//math:go_default_library",
"//proto/engine/v1:go_default_library",
],
objs = ssz_bellatrix_objs,
exclude_objs = ssz_phase0_objs + ssz_altair_objs,
)
ssz_gen_marshal(
name = "ssz_generated_capella",
go_proto = ":go_proto",
out = "capella.ssz.go",
exclude_objs = ssz_phase0_objs + ssz_altair_objs + ssz_bellatrix_objs,
go_proto = ":go_proto",
includes = [
"//consensus-types/primitives:go_default_library",
"//proto/engine/v1:go_default_library",
"//math:go_default_library",
"//proto/engine/v1:go_default_library",
],
objs = ssz_capella_objs,
exclude_objs = ssz_phase0_objs + ssz_altair_objs + ssz_bellatrix_objs,
)
ssz_gen_marshal(
name = "ssz_generated_deneb",
go_proto = ":go_proto",
out = "deneb.ssz.go",
exclude_objs = ssz_phase0_objs + ssz_altair_objs + ssz_bellatrix_objs + ssz_capella_objs,
go_proto = ":go_proto",
includes = [
"//consensus-types/primitives:go_default_library",
"//proto/engine/v1:go_default_library",
"//math:go_default_library",
"//proto/engine/v1:go_default_library",
],
objs = ssz_deneb_objs,
exclude_objs = ssz_phase0_objs + ssz_altair_objs + ssz_bellatrix_objs + ssz_capella_objs,
)
ssz_gen_marshal(
name = "ssz_generated_electra",
go_proto = ":go_proto",
out = "electra.ssz.go",
exclude_objs = ssz_phase0_objs + ssz_altair_objs + ssz_bellatrix_objs + ssz_capella_objs + ssz_deneb_objs,
go_proto = ":go_proto",
includes = [
"//consensus-types/primitives:go_default_library",
"//proto/engine/v1:go_default_library",
"//math:go_default_library",
"//proto/engine/v1:go_default_library",
],
objs = ssz_electra_objs,
exclude_objs = ssz_phase0_objs + ssz_altair_objs + ssz_bellatrix_objs + ssz_capella_objs + ssz_deneb_objs,
)
ssz_gen_marshal(
name = "ssz_generated_non_core",
go_proto = ":go_proto",
out = "non-core.ssz.go",
go_proto = ":go_proto",
includes = [
"//consensus-types/primitives:go_default_library",
"//proto/engine/v1:go_default_library",
"//math:go_default_library",
"//proto/engine/v1:go_default_library",
],
objs = [
"BeaconBlocksByRangeRequest",
@@ -313,13 +313,13 @@ go_library(
"eip_7521.go",
"sync_committee_mainnet.go",
"sync_committee_minimal.go", # keep
":ssz_generated_non_core", # keep
":ssz_generated_phase0", # keep
":ssz_generated_altair", # keep
":ssz_generated_bellatrix", # keep
":ssz_generated_capella", # keep
":ssz_generated_deneb", # keep
":ssz_generated_electra", # keep
":ssz_generated_non_core", # keep
":ssz_generated_phase0", # keep
],
embed = [
":go_grpc_gateway_library",

View File

@@ -1,5 +1,5 @@
// Code generated by fastssz. DO NOT EDIT.
// Hash: 84572d8fa233c45a41477bced891ee355cc1745ae0fad290f110b7f6b5ed12e1
// Hash: 502599304fd370b8602d212eaf1956fe5bf034fe59c75d1a3a6e3db8bcde291a
package eth
import (
@@ -30,20 +30,20 @@ func (a *AttestationElectra) MarshalSSZTo(buf []byte) (dst []byte, err error) {
return
}
// Field (2) 'CommitteeBits'
if size := len(a.CommitteeBits); size != 8 {
err = ssz.ErrBytesLengthFn("--.CommitteeBits", size, 8)
return
}
dst = append(dst, a.CommitteeBits...)
// Field (3) 'Signature'
// Field (2) 'Signature'
if size := len(a.Signature); size != 96 {
err = ssz.ErrBytesLengthFn("--.Signature", size, 96)
return
}
dst = append(dst, a.Signature...)
// Field (3) 'CommitteeBits'
if size := len(a.CommitteeBits); size != 8 {
err = ssz.ErrBytesLengthFn("--.CommitteeBits", size, 8)
return
}
dst = append(dst, a.CommitteeBits...)
// Field (0) 'AggregationBits'
if size := len(a.AggregationBits); size > 131072 {
err = ssz.ErrBytesLengthFn("--.AggregationBits", size, 131072)
@@ -82,17 +82,17 @@ func (a *AttestationElectra) UnmarshalSSZ(buf []byte) error {
return err
}
// Field (2) 'CommitteeBits'
if cap(a.CommitteeBits) == 0 {
a.CommitteeBits = make([]byte, 0, len(buf[132:140]))
}
a.CommitteeBits = append(a.CommitteeBits, buf[132:140]...)
// Field (3) 'Signature'
// Field (2) 'Signature'
if cap(a.Signature) == 0 {
a.Signature = make([]byte, 0, len(buf[140:236]))
a.Signature = make([]byte, 0, len(buf[132:228]))
}
a.Signature = append(a.Signature, buf[140:236]...)
a.Signature = append(a.Signature, buf[132:228]...)
// Field (3) 'CommitteeBits'
if cap(a.CommitteeBits) == 0 {
a.CommitteeBits = make([]byte, 0, len(buf[228:236]))
}
a.CommitteeBits = append(a.CommitteeBits, buf[228:236]...)
// Field (0) 'AggregationBits'
{
@@ -139,20 +139,20 @@ func (a *AttestationElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) {
return
}
// Field (2) 'CommitteeBits'
if size := len(a.CommitteeBits); size != 8 {
err = ssz.ErrBytesLengthFn("--.CommitteeBits", size, 8)
return
}
hh.PutBytes(a.CommitteeBits)
// Field (3) 'Signature'
// Field (2) 'Signature'
if size := len(a.Signature); size != 96 {
err = ssz.ErrBytesLengthFn("--.Signature", size, 96)
return
}
hh.PutBytes(a.Signature)
// Field (3) 'CommitteeBits'
if size := len(a.CommitteeBits); size != 8 {
err = ssz.ErrBytesLengthFn("--.CommitteeBits", size, 8)
return
}
hh.PutBytes(a.CommitteeBits)
hh.Merkleize(indx)
return
}
@@ -653,6 +653,215 @@ func (i *IndexedAttestationElectra) HashTreeRootWith(hh *ssz.Hasher) (err error)
return
}
// MarshalSSZ ssz marshals the SignedBeaconBlockContentsElectra object
func (s *SignedBeaconBlockContentsElectra) MarshalSSZ() ([]byte, error) {
return ssz.MarshalSSZ(s)
}
// MarshalSSZTo ssz marshals the SignedBeaconBlockContentsElectra object to a target array
func (s *SignedBeaconBlockContentsElectra) MarshalSSZTo(buf []byte) (dst []byte, err error) {
dst = buf
offset := int(12)
// Offset (0) 'Block'
dst = ssz.WriteOffset(dst, offset)
if s.Block == nil {
s.Block = new(SignedBeaconBlockElectra)
}
offset += s.Block.SizeSSZ()
// Offset (1) 'KzgProofs'
dst = ssz.WriteOffset(dst, offset)
offset += len(s.KzgProofs) * 48
// Offset (2) 'Blobs'
dst = ssz.WriteOffset(dst, offset)
offset += len(s.Blobs) * 131072
// Field (0) 'Block'
if dst, err = s.Block.MarshalSSZTo(dst); err != nil {
return
}
// Field (1) 'KzgProofs'
if size := len(s.KzgProofs); size > 4096 {
err = ssz.ErrListTooBigFn("--.KzgProofs", size, 4096)
return
}
for ii := 0; ii < len(s.KzgProofs); ii++ {
if size := len(s.KzgProofs[ii]); size != 48 {
err = ssz.ErrBytesLengthFn("--.KzgProofs[ii]", size, 48)
return
}
dst = append(dst, s.KzgProofs[ii]...)
}
// Field (2) 'Blobs'
if size := len(s.Blobs); size > 4096 {
err = ssz.ErrListTooBigFn("--.Blobs", size, 4096)
return
}
for ii := 0; ii < len(s.Blobs); ii++ {
if size := len(s.Blobs[ii]); size != 131072 {
err = ssz.ErrBytesLengthFn("--.Blobs[ii]", size, 131072)
return
}
dst = append(dst, s.Blobs[ii]...)
}
return
}
// UnmarshalSSZ ssz unmarshals the SignedBeaconBlockContentsElectra object
func (s *SignedBeaconBlockContentsElectra) UnmarshalSSZ(buf []byte) error {
var err error
size := uint64(len(buf))
if size < 12 {
return ssz.ErrSize
}
tail := buf
var o0, o1, o2 uint64
// Offset (0) 'Block'
if o0 = ssz.ReadOffset(buf[0:4]); o0 > size {
return ssz.ErrOffset
}
if o0 != 12 {
return ssz.ErrInvalidVariableOffset
}
// Offset (1) 'KzgProofs'
if o1 = ssz.ReadOffset(buf[4:8]); o1 > size || o0 > o1 {
return ssz.ErrOffset
}
// Offset (2) 'Blobs'
if o2 = ssz.ReadOffset(buf[8:12]); o2 > size || o1 > o2 {
return ssz.ErrOffset
}
// Field (0) 'Block'
{
buf = tail[o0:o1]
if s.Block == nil {
s.Block = new(SignedBeaconBlockElectra)
}
if err = s.Block.UnmarshalSSZ(buf); err != nil {
return err
}
}
// Field (1) 'KzgProofs'
{
buf = tail[o1:o2]
num, err := ssz.DivideInt2(len(buf), 48, 4096)
if err != nil {
return err
}
s.KzgProofs = make([][]byte, num)
for ii := 0; ii < num; ii++ {
if cap(s.KzgProofs[ii]) == 0 {
s.KzgProofs[ii] = make([]byte, 0, len(buf[ii*48:(ii+1)*48]))
}
s.KzgProofs[ii] = append(s.KzgProofs[ii], buf[ii*48:(ii+1)*48]...)
}
}
// Field (2) 'Blobs'
{
buf = tail[o2:]
num, err := ssz.DivideInt2(len(buf), 131072, 4096)
if err != nil {
return err
}
s.Blobs = make([][]byte, num)
for ii := 0; ii < num; ii++ {
if cap(s.Blobs[ii]) == 0 {
s.Blobs[ii] = make([]byte, 0, len(buf[ii*131072:(ii+1)*131072]))
}
s.Blobs[ii] = append(s.Blobs[ii], buf[ii*131072:(ii+1)*131072]...)
}
}
return err
}
// SizeSSZ returns the ssz encoded size in bytes for the SignedBeaconBlockContentsElectra object
func (s *SignedBeaconBlockContentsElectra) SizeSSZ() (size int) {
size = 12
// Field (0) 'Block'
if s.Block == nil {
s.Block = new(SignedBeaconBlockElectra)
}
size += s.Block.SizeSSZ()
// Field (1) 'KzgProofs'
size += len(s.KzgProofs) * 48
// Field (2) 'Blobs'
size += len(s.Blobs) * 131072
return
}
// HashTreeRoot ssz hashes the SignedBeaconBlockContentsElectra object
func (s *SignedBeaconBlockContentsElectra) HashTreeRoot() ([32]byte, error) {
return ssz.HashWithDefaultHasher(s)
}
// HashTreeRootWith ssz hashes the SignedBeaconBlockContentsElectra object with a hasher
func (s *SignedBeaconBlockContentsElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) {
indx := hh.Index()
// Field (0) 'Block'
if err = s.Block.HashTreeRootWith(hh); err != nil {
return
}
// Field (1) 'KzgProofs'
{
if size := len(s.KzgProofs); size > 4096 {
err = ssz.ErrListTooBigFn("--.KzgProofs", size, 4096)
return
}
subIndx := hh.Index()
for _, i := range s.KzgProofs {
if len(i) != 48 {
err = ssz.ErrBytesLength
return
}
hh.PutBytes(i)
}
numItems := uint64(len(s.KzgProofs))
hh.MerkleizeWithMixin(subIndx, numItems, 4096)
}
// Field (2) 'Blobs'
{
if size := len(s.Blobs); size > 4096 {
err = ssz.ErrListTooBigFn("--.Blobs", size, 4096)
return
}
subIndx := hh.Index()
for _, i := range s.Blobs {
if len(i) != 131072 {
err = ssz.ErrBytesLength
return
}
hh.PutBytes(i)
}
numItems := uint64(len(s.Blobs))
hh.MerkleizeWithMixin(subIndx, numItems, 4096)
}
hh.Merkleize(indx)
return
}
// MarshalSSZ ssz marshals the SignedBeaconBlockElectra object
func (s *SignedBeaconBlockElectra) MarshalSSZ() ([]byte, error) {
return ssz.MarshalSSZ(s)