Skip to content

Commit 536d647

Browse files
james-prysmrkapka
authored andcommitted
Get blob fulu (OffchainLabs#15610)
* wip * wip * adding ssz marshalling * updating function for readability * adding unit tests and fixing ssz * gaz * linting * fixing test * wip * fixing mock blocker * fixing test * fixing tests and handler * updating unit test for more coverage * adding some comments * self review * gofmt * updating and consolidating tests * moving functional options so it can be used properly * gofmt * more missed gofmt * Update beacon-chain/rpc/endpoints.go Co-authored-by: Radosław Kapka <rkapka@wp.pl> * Update beacon-chain/rpc/lookup/blocker.go Co-authored-by: Radosław Kapka <rkapka@wp.pl> * Update beacon-chain/rpc/eth/beacon/handlers.go Co-authored-by: Radosław Kapka <rkapka@wp.pl> * radek feedback * fixing tests * fixing test * moving endpoint in test * removed unneeded comment * fixing linting from latest develop merge * fixing linting from latest develop merge * Update beacon-chain/rpc/eth/blob/handlers.go Co-authored-by: Radosław Kapka <rkapka@wp.pl> * Update beacon-chain/rpc/eth/blob/handlers.go Co-authored-by: Radosław Kapka <rkapka@wp.pl> * reverting change * reverting change * adding in better error for which hashes are missing * Update beacon-chain/rpc/lookup/blocker.go Co-authored-by: Radosław Kapka <rkapka@wp.pl> * fixing unit test * gofmt --------- Co-authored-by: Radosław Kapka <rkapka@wp.pl>
1 parent d690eee commit 536d647

File tree

14 files changed

+958
-29
lines changed

14 files changed

+958
-29
lines changed

api/server/structs/endpoints_beacon.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,3 +290,9 @@ type GetProposerLookaheadResponse struct {
290290
Finalized bool `json:"finalized"`
291291
Data []string `json:"data"` // validator indexes
292292
}
293+
294+
type GetBlobsResponse struct {
295+
ExecutionOptimistic bool `json:"execution_optimistic"`
296+
Finalized bool `json:"finalized"`
297+
Data []string `json:"data"` //blobs
298+
}

beacon-chain/rpc/endpoints.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,8 @@ func (s *Service) blobEndpoints(blocker lookup.Blocker) []endpoint {
194194
const namespace = "blob"
195195
return []endpoint{
196196
{
197+
// Deprecated: /eth/v1/beacon/blob_sidecars/{block_id} in favor of /eth/v1/beacon/blobs/{block_id}
198+
// the endpoint will continue to work post fulu for some time however
197199
template: "/eth/v1/beacon/blob_sidecars/{block_id}",
198200
name: namespace + ".Blobs",
199201
middleware: []middleware.Middleware{
@@ -203,6 +205,16 @@ func (s *Service) blobEndpoints(blocker lookup.Blocker) []endpoint {
203205
handler: server.Blobs,
204206
methods: []string{http.MethodGet},
205207
},
208+
{
209+
template: "/eth/v1/beacon/blobs/{block_id}",
210+
name: namespace + ".GetBlobs",
211+
middleware: []middleware.Middleware{
212+
middleware.AcceptHeaderHandler([]string{api.JsonMediaType, api.OctetStreamMediaType}),
213+
middleware.AcceptEncodingHeaderHandler(),
214+
},
215+
handler: server.GetBlobs,
216+
methods: []string{http.MethodGet},
217+
},
206218
}
207219
}
208220

beacon-chain/rpc/endpoints_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ func Test_endpoints(t *testing.T) {
7070

7171
blobRoutes := map[string][]string{
7272
"/eth/v1/beacon/blob_sidecars/{block_id}": {http.MethodGet},
73+
"/eth/v1/beacon/blobs/{block_id}": {http.MethodGet},
7374
}
7475

7576
configRoutes := map[string][]string{

beacon-chain/rpc/eth/blob/BUILD.bazel

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ go_library(
1313
"//api/server/structs:go_default_library",
1414
"//beacon-chain/blockchain:go_default_library",
1515
"//beacon-chain/rpc/core:go_default_library",
16+
"//beacon-chain/rpc/eth/shared:go_default_library",
1617
"//beacon-chain/rpc/lookup:go_default_library",
18+
"//beacon-chain/rpc/options:go_default_library",
1719
"//config/fieldparams:go_default_library",
1820
"//config/params:go_default_library",
1921
"//consensus-types/blocks:go_default_library",
@@ -33,6 +35,7 @@ go_test(
3335
deps = [
3436
"//api:go_default_library",
3537
"//api/server/structs:go_default_library",
38+
"//beacon-chain/blockchain/kzg:go_default_library",
3639
"//beacon-chain/blockchain/testing:go_default_library",
3740
"//beacon-chain/db/filesystem:go_default_library",
3841
"//beacon-chain/db/testing:go_default_library",
@@ -41,6 +44,7 @@ go_test(
4144
"//beacon-chain/verification:go_default_library",
4245
"//config/fieldparams:go_default_library",
4346
"//config/params:go_default_library",
47+
"//consensus-types/primitives:go_default_library",
4448
"//network/httputil:go_default_library",
4549
"//proto/prysm/v1alpha1:go_default_library",
4650
"//runtime/version:go_default_library",

beacon-chain/rpc/eth/blob/handlers.go

Lines changed: 96 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ import (
1010
"github.com/OffchainLabs/prysm/v6/api"
1111
"github.com/OffchainLabs/prysm/v6/api/server/structs"
1212
"github.com/OffchainLabs/prysm/v6/beacon-chain/rpc/core"
13-
field_params "github.com/OffchainLabs/prysm/v6/config/fieldparams"
13+
"github.com/OffchainLabs/prysm/v6/beacon-chain/rpc/eth/shared"
14+
"github.com/OffchainLabs/prysm/v6/beacon-chain/rpc/options"
15+
fieldparams "github.com/OffchainLabs/prysm/v6/config/fieldparams"
1416
"github.com/OffchainLabs/prysm/v6/config/params"
1517
"github.com/OffchainLabs/prysm/v6/consensus-types/blocks"
1618
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
@@ -22,6 +24,8 @@ import (
2224
)
2325

2426
// Blobs is an HTTP handler for Beacon API getBlobs.
27+
// Deprecated: /eth/v1/beacon/blob_sidecars/{block_id} in favor of /eth/v1/beacon/blobs/{block_id}
28+
// the endpoint will continue to work post fulu for some time however
2529
func (s *Server) Blobs(w http.ResponseWriter, r *http.Request) {
2630
ctx, span := trace.StartSpan(r.Context(), "beacon.Blobs")
2731
defer span.End()
@@ -34,7 +38,7 @@ func (s *Server) Blobs(w http.ResponseWriter, r *http.Request) {
3438
segments := strings.Split(r.URL.Path, "/")
3539
blockId := segments[len(segments)-1]
3640

37-
verifiedBlobs, rpcErr := s.Blocker.Blobs(ctx, blockId, indices)
41+
verifiedBlobs, rpcErr := s.Blocker.Blobs(ctx, blockId, options.WithIndices(indices))
3842
if rpcErr != nil {
3943
code := core.ErrorReasonToHTTP(rpcErr.Reason)
4044
switch code {
@@ -127,6 +131,94 @@ loop:
127131
return indices, nil
128132
}
129133

134+
// GetBlobs retrieves blobs for a given block id. ( this is the new handler that replaces func (s *Server) Blobs )
135+
func (s *Server) GetBlobs(w http.ResponseWriter, r *http.Request) {
136+
ctx, span := trace.StartSpan(r.Context(), "beacon.GetBlobs")
137+
defer span.End()
138+
139+
segments := strings.Split(r.URL.Path, "/")
140+
blockId := segments[len(segments)-1]
141+
142+
var verifiedBlobs []*blocks.VerifiedROBlob
143+
var rpcErr *core.RpcError
144+
145+
// Check if versioned_hashes parameter is provided
146+
versionedHashesStr := r.URL.Query()["versioned_hashes"]
147+
versionedHashes := make([][]byte, len(versionedHashesStr))
148+
if len(versionedHashesStr) > 0 {
149+
for i, hashStr := range versionedHashesStr {
150+
hash, ok := shared.ValidateHex(w, fmt.Sprintf("versioned_hashes[%d]", i), hashStr, 32)
151+
if !ok {
152+
return
153+
}
154+
versionedHashes[i] = hash
155+
}
156+
}
157+
verifiedBlobs, rpcErr = s.Blocker.Blobs(ctx, blockId, options.WithVersionedHashes(versionedHashes))
158+
if rpcErr != nil {
159+
code := core.ErrorReasonToHTTP(rpcErr.Reason)
160+
switch code {
161+
case http.StatusBadRequest:
162+
httputil.HandleError(w, "Bad Request: "+rpcErr.Err.Error(), code)
163+
return
164+
case http.StatusNotFound:
165+
httputil.HandleError(w, "Not found: "+rpcErr.Err.Error(), code)
166+
return
167+
case http.StatusInternalServerError:
168+
httputil.HandleError(w, "Internal server error: "+rpcErr.Err.Error(), code)
169+
return
170+
default:
171+
httputil.HandleError(w, rpcErr.Err.Error(), code)
172+
return
173+
}
174+
}
175+
176+
blk, err := s.Blocker.Block(ctx, []byte(blockId))
177+
if err != nil {
178+
httputil.HandleError(w, "Could not fetch block: "+err.Error(), http.StatusInternalServerError)
179+
return
180+
}
181+
if blk == nil {
182+
httputil.HandleError(w, "Block not found", http.StatusNotFound)
183+
return
184+
}
185+
186+
if httputil.RespondWithSsz(r) {
187+
sszLen := fieldparams.BlobSize
188+
sszData := make([]byte, len(verifiedBlobs)*sszLen)
189+
for i := range verifiedBlobs {
190+
copy(sszData[i*sszLen:(i+1)*sszLen], verifiedBlobs[i].Blob)
191+
}
192+
193+
w.Header().Set(api.VersionHeader, version.String(blk.Version()))
194+
httputil.WriteSsz(w, sszData)
195+
return
196+
}
197+
198+
blkRoot, err := blk.Block().HashTreeRoot()
199+
if err != nil {
200+
httputil.HandleError(w, "Could not hash block: "+err.Error(), http.StatusInternalServerError)
201+
return
202+
}
203+
isOptimistic, err := s.OptimisticModeFetcher.IsOptimisticForRoot(ctx, blkRoot)
204+
if err != nil {
205+
httputil.HandleError(w, "Could not check if block is optimistic: "+err.Error(), http.StatusInternalServerError)
206+
return
207+
}
208+
209+
data := make([]string, len(verifiedBlobs))
210+
for i, v := range verifiedBlobs {
211+
data[i] = hexutil.Encode(v.Blob)
212+
}
213+
resp := &structs.GetBlobsResponse{
214+
Data: data,
215+
ExecutionOptimistic: isOptimistic,
216+
Finalized: s.FinalizationFetcher.IsFinalized(ctx, blkRoot),
217+
}
218+
w.Header().Set(api.VersionHeader, version.String(blk.Version()))
219+
httputil.WriteJson(w, resp)
220+
}
221+
130222
func buildSidecarsJsonResponse(verifiedBlobs []*blocks.VerifiedROBlob) []*structs.Sidecar {
131223
sidecars := make([]*structs.Sidecar, len(verifiedBlobs))
132224
for i, sc := range verifiedBlobs {
@@ -147,13 +239,13 @@ func buildSidecarsJsonResponse(verifiedBlobs []*blocks.VerifiedROBlob) []*struct
147239
}
148240

149241
func buildSidecarsSSZResponse(verifiedBlobs []*blocks.VerifiedROBlob) ([]byte, error) {
150-
ssz := make([]byte, field_params.BlobSidecarSize*len(verifiedBlobs))
242+
ssz := make([]byte, fieldparams.BlobSidecarSize*len(verifiedBlobs))
151243
for i, sidecar := range verifiedBlobs {
152244
sszrep, err := sidecar.MarshalSSZ()
153245
if err != nil {
154246
return nil, errors.Wrap(err, "failed to marshal sidecar ssz")
155247
}
156-
copy(ssz[i*field_params.BlobSidecarSize:(i+1)*field_params.BlobSidecarSize], sszrep)
248+
copy(ssz[i*fieldparams.BlobSidecarSize:(i+1)*fieldparams.BlobSidecarSize], sszrep)
157249
}
158250
return ssz, nil
159251
}

0 commit comments

Comments
 (0)