-
Notifications
You must be signed in to change notification settings - Fork 3.9k
beacon client: use new fusaka endpoint to get blobs #17736
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
4a8bd0a
da52756
be53dde
ccbfaec
4245b4a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -25,6 +25,7 @@ const ( | |||||||||||||||||||||||||
| specMethod = "eth/v1/config/spec" | ||||||||||||||||||||||||||
| genesisMethod = "eth/v1/beacon/genesis" | ||||||||||||||||||||||||||
| sidecarsMethodPrefix = "eth/v1/beacon/blob_sidecars/" | ||||||||||||||||||||||||||
| blobsMethodPrefix = "eth/v1/beacon/blobs/" | ||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| type L1BeaconClientConfig struct { | ||||||||||||||||||||||||||
|
|
@@ -100,6 +101,19 @@ func (cl *BeaconHTTPClient) BeaconGenesis(ctx context.Context) (eth.APIGenesisRe | |||||||||||||||||||||||||
| return genesisResp, nil | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| func (cl *BeaconHTTPClient) BeaconBlobs(ctx context.Context, slot uint64, hashes []eth.IndexedBlobHash) ([]*eth.Blob, error) { | ||||||||||||||||||||||||||
| reqQuery := url.Values{} | ||||||||||||||||||||||||||
| for _, hash := range hashes { | ||||||||||||||||||||||||||
| reqQuery.Add("versioned_hashes", hash.Hash.Hex()) | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| reqPath := path.Join(blobsMethodPrefix, strconv.FormatUint(slot, 10)) | ||||||||||||||||||||||||||
| var blobsResp []*eth.Blob | ||||||||||||||||||||||||||
| if err := cl.apiReq(ctx, &blobsResp, reqPath, reqQuery); err != nil { | ||||||||||||||||||||||||||
| return nil, err | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| return blobsResp, nil | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| func (cl *BeaconHTTPClient) BeaconBlobSideCars(ctx context.Context, fetchAllSidecars bool, slot uint64, hashes []eth.IndexedBlobHash) (eth.APIGetBlobSidecarsResponse, error) { | ||||||||||||||||||||||||||
| reqPath := path.Join(sidecarsMethodPrefix, strconv.FormatUint(slot, 10)) | ||||||||||||||||||||||||||
| var reqQuery url.Values | ||||||||||||||||||||||||||
|
|
@@ -170,8 +184,8 @@ func NewL1BeaconClient(cl apis.BeaconClient, cfg L1BeaconClientConfig, fallbacks | |||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| type TimeToSlotFn func(timestamp uint64) (uint64, error) | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| // GetTimeToSlotFn returns a function that converts a timestamp to a slot number. | ||||||||||||||||||||||||||
| func (cl *L1BeaconClient) GetTimeToSlotFn(ctx context.Context) (TimeToSlotFn, error) { | ||||||||||||||||||||||||||
| // getTimeToSlotFn returns a function that converts a timestamp to a slot number. | ||||||||||||||||||||||||||
| func (cl *L1BeaconClient) getTimeToSlotFn(ctx context.Context) (TimeToSlotFn, error) { | ||||||||||||||||||||||||||
| cl.initLock.Lock() | ||||||||||||||||||||||||||
| defer cl.initLock.Unlock() | ||||||||||||||||||||||||||
| if cl.timeToSlotFn != nil { | ||||||||||||||||||||||||||
|
|
@@ -202,6 +216,18 @@ func (cl *L1BeaconClient) GetTimeToSlotFn(ctx context.Context) (TimeToSlotFn, er | |||||||||||||||||||||||||
| return cl.timeToSlotFn, nil | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| func (cl *L1BeaconClient) timeToSlot(ctx context.Context, timestamp uint64) (uint64, error) { | ||||||||||||||||||||||||||
| slotFn, err := cl.getTimeToSlotFn(ctx) | ||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||
| return 0, fmt.Errorf("get time to slot fn: %w", err) | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| slot, err := slotFn(timestamp) | ||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||
| return 0, fmt.Errorf("convert timestamp %d to slot number: %w", timestamp, err) | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| return slot, nil | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| func (cl *L1BeaconClient) fetchSidecars(ctx context.Context, slot uint64, hashes []eth.IndexedBlobHash) (eth.APIGetBlobSidecarsResponse, error) { | ||||||||||||||||||||||||||
| var errs []error | ||||||||||||||||||||||||||
| for i := 0; i < cl.pool.Len(); i++ { | ||||||||||||||||||||||||||
|
|
@@ -225,18 +251,21 @@ func (cl *L1BeaconClient) GetBlobSidecars(ctx context.Context, ref eth.L1BlockRe | |||||||||||||||||||||||||
| if len(hashes) == 0 { | ||||||||||||||||||||||||||
| return []*eth.BlobSidecar{}, nil | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| slotFn, err := cl.GetTimeToSlotFn(ctx) | ||||||||||||||||||||||||||
| slot, err := cl.timeToSlot(ctx, ref.Time) | ||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||
| return nil, fmt.Errorf("failed to get time to slot function: %w", err) | ||||||||||||||||||||||||||
| return nil, err | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| slot, err := slotFn(ref.Time) | ||||||||||||||||||||||||||
| sidecars, err := cl.getBlobSidecars(ctx, slot, hashes) | ||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||
| return nil, fmt.Errorf("error in converting ref.Time to slot: %w", err) | ||||||||||||||||||||||||||
| return nil, fmt.Errorf("get blob sidecars for block %v: %w", ref, err) | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| return sidecars, nil | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| func (cl *L1BeaconClient) getBlobSidecars(ctx context.Context, slot uint64, hashes []eth.IndexedBlobHash) ([]*eth.BlobSidecar, error) { | ||||||||||||||||||||||||||
| resp, err := cl.fetchSidecars(ctx, slot, hashes) | ||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||
| return nil, fmt.Errorf("failed to fetch blob sidecars for slot %v block %v: %w", slot, ref, err) | ||||||||||||||||||||||||||
| return nil, fmt.Errorf("failed to fetch blob sidecars for slot %v: %w", slot, err) | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| apiscs := make([]*eth.APIBlobSidecar, 0, len(hashes)) | ||||||||||||||||||||||||||
|
|
@@ -267,17 +296,37 @@ func (cl *L1BeaconClient) GetBlobSidecars(ctx context.Context, ref eth.L1BlockRe | |||||||||||||||||||||||||
| // blob's validity by checking its proof against the commitment, and confirming the commitment | ||||||||||||||||||||||||||
| // hashes to the expected value. Returns error if any blob is found invalid. | ||||||||||||||||||||||||||
| func (cl *L1BeaconClient) GetBlobs(ctx context.Context, ref eth.L1BlockRef, hashes []eth.IndexedBlobHash) ([]*eth.Blob, error) { | ||||||||||||||||||||||||||
| blobSidecars, err := cl.GetBlobSidecars(ctx, ref, hashes) | ||||||||||||||||||||||||||
| if len(hashes) == 0 { | ||||||||||||||||||||||||||
| return []*eth.Blob{}, nil | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| slot, err := cl.timeToSlot(ctx, ref.Time) | ||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||
| return nil, fmt.Errorf("failed to get blob sidecars for L1BlockRef %s: %w", ref, err) | ||||||||||||||||||||||||||
| return nil, err | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| blobs, err := blobsFromSidecars(blobSidecars, hashes) | ||||||||||||||||||||||||||
| blobs, err := cl.cl.BeaconBlobs(ctx, slot, hashes) | ||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||
| return nil, fmt.Errorf("failed to get blobs from sidecars for L1BlockRef %s: %w", ref, err) | ||||||||||||||||||||||||||
| // We would normally check for an explicit error like "method not found", but the Beacon | ||||||||||||||||||||||||||
| // API doesn't standardize such a response. Thus, we interpret all errors as | ||||||||||||||||||||||||||
| // "method not found" and fall back to fetching sidecars. | ||||||||||||||||||||||||||
| blobSidecars, err := cl.getBlobSidecars(ctx, slot, hashes) | ||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||
| return nil, fmt.Errorf("failed to get blob sidecars for L1BlockRef %s: %w", ref, err) | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| blobs, err := blobsFromSidecars(blobSidecars, hashes) | ||||||||||||||||||||||||||
joshklop marked this conversation as resolved.
Show resolved
Hide resolved
Comment on lines
+311
to
+315
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suggest we set a state variable like
Suggested change
This state variable would be checked above before calling |
||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||
| return nil, fmt.Errorf("failed to get blobs from sidecars for L1BlockRef %s: %w", ref, err) | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| return blobs, nil | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| for i, blob := range blobs { | ||||||||||||||||||||||||||
| if err := verifyBlob(blob, hashes[i].Hash); err != nil { | ||||||||||||||||||||||||||
| return nil, fmt.Errorf("blob %d failed verification: %w", i, err) | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| return blobs, nil | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| // blobsFromSidecars pulls the blobs from the sidecars and verifies them against the supplied hashes. | ||||||||||||||||||||||||||
| func blobsFromSidecars(blobSidecars []*eth.BlobSidecar, hashes []eth.IndexedBlobHash) ([]*eth.Blob, error) { | ||||||||||||||||||||||||||
| if len(blobSidecars) != len(hashes) { | ||||||||||||||||||||||||||
| return nil, fmt.Errorf("number of hashes and blobSidecars mismatch, %d != %d", len(hashes), len(blobSidecars)) | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Uh oh!
There was an error while loading. Please reload this page.