diff --git a/beacon-chain/rpc/apimiddleware/BUILD.bazel b/beacon-chain/rpc/apimiddleware/BUILD.bazel index af07e5fa6a1..9ad9a91f868 100644 --- a/beacon-chain/rpc/apimiddleware/BUILD.bazel +++ b/beacon-chain/rpc/apimiddleware/BUILD.bazel @@ -18,6 +18,7 @@ go_library( "//beacon-chain/rpc/eth/helpers:go_default_library", "//config/params:go_default_library", "//consensus-types/primitives:go_default_library", + "//network: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 1e12e54188e..246e2ae4cc6 100644 --- a/beacon-chain/rpc/apimiddleware/custom_handlers.go +++ b/beacon-chain/rpc/apimiddleware/custom_handlers.go @@ -8,13 +8,13 @@ import ( "fmt" "io" "net/http" - "regexp" "strconv" "strings" "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" + "github.com/prysmaticlabs/prysm/v4/network" "github.com/prysmaticlabs/prysm/v4/runtime/version" "github.com/r3labs/sse" ) @@ -26,9 +26,6 @@ const ( octetStreamMediaType = "application/octet-stream" ) -// match a number with optional decimals -var priorityRegex = regexp.MustCompile(`q=(\d+(?:\.\d+)?)`) - type sszConfig struct { fileName string responseJson SszResponse @@ -120,7 +117,7 @@ func handleGetSSZ( req *http.Request, config sszConfig, ) (handled bool) { - ssz, err := sszRequested(req) + ssz, err := network.SszRequested(req) if err != nil { apimiddleware.WriteError(w, apimiddleware.InternalServerError(err), nil) return true @@ -213,44 +210,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 != jsonMediaType && name != octetStreamMediaType { - continue - } - // no params specified - if len(values) == 1 { - priority := 1.0 - if priority > currentPriority { - currentType, currentPriority = name, priority - } - continue - } - params := values[1] - match := priorityRegex.FindAllStringSubmatch(params, 1) - if len(match) != 1 { - continue - } - priority, err := strconv.ParseFloat(match[0][1], 32) - if err != nil { - return false, err - } - if priority > currentPriority { - currentType, currentPriority = name, priority - } - } - - return currentType == octetStreamMediaType, nil -} - 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 c0c09758bbd..268f402fa9e 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" @@ -42,95 +41,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{octetStreamMediaType} - result, err := sszRequested(request) - require.NoError(t, err) - assert.Equal(t, true, result) - }) - - t.Run("ssz_content_type_first", func(t *testing.T) { - request := httptest.NewRequest("GET", "http://foo.example", nil) - request.Header["Accept"] = []string{fmt.Sprintf("%s,%s", octetStreamMediaType, jsonMediaType)} - result, err := sszRequested(request) - require.NoError(t, err) - assert.Equal(t, true, result) - }) - - t.Run("ssz_content_type_preferred_1", func(t *testing.T) { - request := httptest.NewRequest("GET", "http://foo.example", nil) - request.Header["Accept"] = []string{fmt.Sprintf("%s;q=0.9,%s", jsonMediaType, octetStreamMediaType)} - result, err := sszRequested(request) - require.NoError(t, err) - assert.Equal(t, true, result) - }) - - t.Run("ssz_content_type_preferred_2", func(t *testing.T) { - request := httptest.NewRequest("GET", "http://foo.example", nil) - request.Header["Accept"] = []string{fmt.Sprintf("%s;q=0.95,%s;q=0.9", octetStreamMediaType, jsonMediaType)} - result, err := sszRequested(request) - require.NoError(t, err) - assert.Equal(t, true, result) - }) - - t.Run("other_content_type_preferred", func(t *testing.T) { - request := httptest.NewRequest("GET", "http://foo.example", nil) - request.Header["Accept"] = []string{fmt.Sprintf("%s,%s;q=0.9", jsonMediaType, octetStreamMediaType)} - result, err := sszRequested(request) - require.NoError(t, err) - assert.Equal(t, false, result) - }) - - t.Run("other_params", func(t *testing.T) { - request := httptest.NewRequest("GET", "http://foo.example", nil) - request.Header["Accept"] = []string{fmt.Sprintf("%s,%s;q=0.9,otherparam=xyz", jsonMediaType, octetStreamMediaType)} - result, err := sszRequested(request) - require.NoError(t, err) - assert.Equal(t, false, result) - }) - - t.Run("no_header", func(t *testing.T) { - request := httptest.NewRequest("GET", "http://foo.example", nil) - result, err := sszRequested(request) - require.NoError(t, err) - assert.Equal(t, false, result) - }) - - t.Run("empty_header", func(t *testing.T) { - request := httptest.NewRequest("GET", "http://foo.example", nil) - request.Header["Accept"] = []string{} - result, err := sszRequested(request) - require.NoError(t, err) - assert.Equal(t, false, result) - }) - - t.Run("empty_header_value", func(t *testing.T) { - request := httptest.NewRequest("GET", "http://foo.example", nil) - request.Header["Accept"] = []string{""} - result, err := sszRequested(request) - require.NoError(t, err) - assert.Equal(t, false, result) - }) - - t.Run("other_content_type", func(t *testing.T) { - request := httptest.NewRequest("GET", "http://foo.example", nil) - request.Header["Accept"] = []string{"application/other"} - result, err := sszRequested(request) - require.NoError(t, err) - assert.Equal(t, false, result) - }) - - t.Run("garbage", func(t *testing.T) { - request := httptest.NewRequest("GET", "http://foo.example", nil) - request.Header["Accept"] = []string{"This is Sparta!!!"} - result, err := sszRequested(request) - require.NoError(t, err) - assert.Equal(t, false, result) - }) -} - 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 index 56ad23deb85..10f8ea918bc 100644 --- a/beacon-chain/rpc/eth/blob/BUILD.bazel +++ b/beacon-chain/rpc/eth/blob/BUILD.bazel @@ -19,6 +19,8 @@ go_library( "//consensus-types/primitives:go_default_library", "//encoding/bytesutil:go_default_library", "//network: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", @@ -33,6 +35,7 @@ go_test( 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:go_default_library", diff --git a/beacon-chain/rpc/eth/blob/handlers.go b/beacon-chain/rpc/eth/blob/handlers.go index 4b9ca28cd15..c80d30ab4f0 100644 --- a/beacon-chain/rpc/eth/blob/handlers.go +++ b/beacon-chain/rpc/eth/blob/handlers.go @@ -15,6 +15,8 @@ import ( "github.com/prysmaticlabs/prysm/v4/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v4/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v4/network" + 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" ) @@ -131,6 +133,43 @@ func (s *Server) Blobs(w http.ResponseWriter, r *http.Request) { network.WriteError(w, errJson) return } + + ssz, err := network.SszRequested(r) + if err != nil { + errJson := &network.DefaultErrorJson{ + Message: err.Error(), + Code: http.StatusInternalServerError, + } + network.WriteError(w, errJson) + return + } + + if ssz { + v2sidecars, err := migration.V1Alpha1BlobSidecarsToV2(sidecars) + if err != nil { + errJson := &network.DefaultErrorJson{ + Message: err.Error(), + Code: http.StatusInternalServerError, + } + network.WriteError(w, errJson) + return + } + sidecarResp := ðpb.BlobSidecars{ + Sidecars: v2sidecars, + } + sszResp, err := sidecarResp.MarshalSSZ() + if err != nil { + errJson := &network.DefaultErrorJson{ + Message: err.Error(), + Code: http.StatusInternalServerError, + } + network.WriteError(w, errJson) + return + } + network.WriteSsz(w, sszResp, "blob_sidecars.ssz") + return + } + network.WriteJson(w, buildSidecardsResponse(sidecars)) } diff --git a/beacon-chain/rpc/eth/blob/handlers_test.go b/beacon-chain/rpc/eth/blob/handlers_test.go index 5f22652be5d..9b6b96b9d08 100644 --- a/beacon-chain/rpc/eth/blob/handlers_test.go +++ b/beacon-chain/rpc/eth/blob/handlers_test.go @@ -13,6 +13,7 @@ import ( "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" "github.com/prysmaticlabs/prysm/v4/network" @@ -270,4 +271,33 @@ func TestBlobs(t *testing.T) { 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/network/BUILD.bazel b/network/BUILD.bazel index c0b9bb9916f..0e168fc3744 100644 --- a/network/BUILD.bazel +++ b/network/BUILD.bazel @@ -6,6 +6,7 @@ go_library( "auth.go", "endpoint.go", "external_ip.go", + "reader.go", "writer.go", ], importpath = "github.com/prysmaticlabs/prysm/v4/network", @@ -25,13 +26,18 @@ go_test( "auth_test.go", "endpoint_test.go", "external_ip_test.go", + "reader_test.go", + "writer_test.go", ], embed = [":go_default_library"], deps = [ + "//config/fieldparams:go_default_library", "//encoding/bytesutil:go_default_library", "//network/authorization: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", "@com_github_golang_jwt_jwt_v4//:go_default_library", "@com_github_sirupsen_logrus//hooks/test:go_default_library", ], diff --git a/network/reader.go b/network/reader.go new file mode 100644 index 00000000000..99a24cecc4a --- /dev/null +++ b/network/reader.go @@ -0,0 +1,51 @@ +package network + +import ( + "net/http" + "regexp" + "strconv" + "strings" +) + +// match a number with optional decimals +var priorityRegex = regexp.MustCompile(`q=(\d+(?:\.\d+)?)`) + +// SszRequested takes a http request and checks to see if it should be requesting a ssz response. +func SszRequested(req *http.Request) (bool, error) { + accept := req.Header.Values("Accept") + if len(accept) == 0 { + return false, nil + } + types := strings.Split(accept[0], ",") + currentType, currentPriority := "", 0.0 + for _, t := range types { + values := strings.Split(t, ";") + name := values[0] + if name != jsonMediaType && name != octetStreamMediaType { + continue + } + // no params specified + if len(values) == 1 { + priority := 1.0 + if priority > currentPriority { + currentType, currentPriority = name, priority + } + continue + } + params := values[1] + + match := priorityRegex.FindAllStringSubmatch(params, 1) + if len(match) != 1 { + continue + } + priority, err := strconv.ParseFloat(match[0][1], 32) + if err != nil { + return false, err + } + if priority > currentPriority { + currentType, currentPriority = name, priority + } + } + + return currentType == octetStreamMediaType, nil +} diff --git a/network/reader_test.go b/network/reader_test.go new file mode 100644 index 00000000000..b454addcadc --- /dev/null +++ b/network/reader_test.go @@ -0,0 +1,99 @@ +package network + +import ( + "fmt" + "net/http/httptest" + "testing" + + "github.com/prysmaticlabs/prysm/v4/testing/assert" + "github.com/prysmaticlabs/prysm/v4/testing/require" +) + +func TestSSZRequested(t *testing.T) { + t.Run("ssz_requested", func(t *testing.T) { + request := httptest.NewRequest("GET", "http://foo.example", nil) + request.Header["Accept"] = []string{octetStreamMediaType} + result, err := SszRequested(request) + require.NoError(t, err) + assert.Equal(t, true, result) + }) + + t.Run("ssz_content_type_first", func(t *testing.T) { + request := httptest.NewRequest("GET", "http://foo.example", nil) + request.Header["Accept"] = []string{fmt.Sprintf("%s,%s", octetStreamMediaType, jsonMediaType)} + result, err := SszRequested(request) + require.NoError(t, err) + assert.Equal(t, true, result) + }) + + t.Run("ssz_content_type_preferred_1", func(t *testing.T) { + request := httptest.NewRequest("GET", "http://foo.example", nil) + request.Header["Accept"] = []string{fmt.Sprintf("%s;q=0.9,%s", jsonMediaType, octetStreamMediaType)} + result, err := SszRequested(request) + require.NoError(t, err) + assert.Equal(t, true, result) + }) + + t.Run("ssz_content_type_preferred_2", func(t *testing.T) { + request := httptest.NewRequest("GET", "http://foo.example", nil) + request.Header["Accept"] = []string{fmt.Sprintf("%s;q=0.95,%s;q=0.9", octetStreamMediaType, jsonMediaType)} + result, err := SszRequested(request) + require.NoError(t, err) + assert.Equal(t, true, result) + }) + + t.Run("other_content_type_preferred", func(t *testing.T) { + request := httptest.NewRequest("GET", "http://foo.example", nil) + request.Header["Accept"] = []string{fmt.Sprintf("%s,%s;q=0.9", jsonMediaType, octetStreamMediaType)} + result, err := SszRequested(request) + require.NoError(t, err) + assert.Equal(t, false, result) + }) + + t.Run("other_params", func(t *testing.T) { + request := httptest.NewRequest("GET", "http://foo.example", nil) + request.Header["Accept"] = []string{fmt.Sprintf("%s,%s;q=0.9,otherparam=xyz", jsonMediaType, octetStreamMediaType)} + result, err := SszRequested(request) + require.NoError(t, err) + assert.Equal(t, false, result) + }) + + t.Run("no_header", func(t *testing.T) { + request := httptest.NewRequest("GET", "http://foo.example", nil) + result, err := SszRequested(request) + require.NoError(t, err) + assert.Equal(t, false, result) + }) + + t.Run("empty_header", func(t *testing.T) { + request := httptest.NewRequest("GET", "http://foo.example", nil) + request.Header["Accept"] = []string{} + result, err := SszRequested(request) + require.NoError(t, err) + assert.Equal(t, false, result) + }) + + t.Run("empty_header_value", func(t *testing.T) { + request := httptest.NewRequest("GET", "http://foo.example", nil) + request.Header["Accept"] = []string{""} + result, err := SszRequested(request) + require.NoError(t, err) + assert.Equal(t, false, result) + }) + + t.Run("other_content_type", func(t *testing.T) { + request := httptest.NewRequest("GET", "http://foo.example", nil) + request.Header["Accept"] = []string{"application/other"} + result, err := SszRequested(request) + require.NoError(t, err) + assert.Equal(t, false, result) + }) + + t.Run("garbage", func(t *testing.T) { + request := httptest.NewRequest("GET", "http://foo.example", nil) + request.Header["Accept"] = []string{"This is Sparta!!!"} + result, err := SszRequested(request) + require.NoError(t, err) + assert.Equal(t, false, result) + }) +} diff --git a/network/writer.go b/network/writer.go index f7b886a1622..988d364ca43 100644 --- a/network/writer.go +++ b/network/writer.go @@ -10,6 +10,11 @@ import ( log "github.com/sirupsen/logrus" ) +const ( + jsonMediaType = "application/json" + octetStreamMediaType = "application/octet-stream" +) + // DefaultErrorJson is a JSON representation of a simple error value, containing only a message and an error code. type DefaultErrorJson struct { Message string `json:"message"` @@ -18,13 +23,23 @@ type DefaultErrorJson struct { // WriteJson writes the response message in JSON format. func WriteJson(w http.ResponseWriter, v any) { - w.Header().Set("Content-Type", "application/json") + w.Header().Set("Content-Type", jsonMediaType) w.WriteHeader(http.StatusOK) if err := json.NewEncoder(w).Encode(v); err != nil { log.WithError(err).Error("Could not write response message") } } +// WriteSsz writes the response message in ssz format +func WriteSsz(w http.ResponseWriter, respSsz []byte, fileName string) { + w.Header().Set("Content-Length", strconv.Itoa(len(respSsz))) + w.Header().Set("Content-Type", octetStreamMediaType) + w.Header().Set("Content-Disposition", "attachment; filename="+fileName) + if _, err := io.Copy(w, io.NopCloser(bytes.NewReader(respSsz))); err != nil { + log.WithError(err).Error("could not write response message") + } +} + // WriteError writes the error by manipulating headers and the body of the final response. func WriteError(w http.ResponseWriter, errJson *DefaultErrorJson) { j, err := json.Marshal(errJson) diff --git a/network/writer_test.go b/network/writer_test.go new file mode 100644 index 00000000000..4a733ac5dd2 --- /dev/null +++ b/network/writer_test.go @@ -0,0 +1,35 @@ +package network + +import ( + "fmt" + "net/http/httptest" + "strings" + "testing" + + "github.com/ethereum/go-ethereum/common/hexutil" + fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams" + eth "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v4/testing/require" +) + +func TestWriteSsz(t *testing.T) { + name := "test.ssz" + sidecar := ð.BlobSidecar{ + BlockRoot: make([]byte, fieldparams.RootLength), + Index: 0, + Slot: 0, + BlockParentRoot: make([]byte, fieldparams.RootLength), + ProposerIndex: 123, + Blob: make([]byte, fieldparams.BlobLength), + KzgCommitment: make([]byte, fieldparams.BLSPubkeyLength), + KzgProof: make([]byte, fieldparams.BLSPubkeyLength), + } + respSsz, err := sidecar.MarshalSSZ() + require.NoError(t, err) + writer := httptest.NewRecorder() + WriteSsz(writer, respSsz, name) + require.Equal(t, writer.Header().Get("Content-Type"), "application/octet-stream") + require.Equal(t, true, strings.Contains(writer.Header().Get("Content-Disposition"), name)) + require.Equal(t, writer.Header().Get("Content-Length"), fmt.Sprintf("%v", len(respSsz))) + require.Equal(t, hexutil.Encode(writer.Body.Bytes()), hexutil.Encode(respSsz)) +} diff --git a/proto/eth/v2/BUILD.bazel b/proto/eth/v2/BUILD.bazel index ff558827acc..cfc26696e28 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 f89be70d2d8..4c5318ddde8 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, + 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, 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, + 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, 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, + 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 9fd564af25b..5570330f67d 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 e7e608b135d..9eb3ec5da68 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 1fc9a254c24..c1ebb7b31ab 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 46baaaa5180..228fcd57bc5 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/testing/util/blob.go b/testing/util/blob.go index 291aa25403d..46dde40106f 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 {