@@ -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
2529func (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+
130222func 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
149241func 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