Skip to content

Commit d41cfb5

Browse files
committed
refactor: prefer blob_sidecars endpoint to avoid recomputing KZG proofs
Switch to prioritizing /eth/v1/beacon/blob_sidecars over /eth/v1/beacon/blobs since the sidecars endpoint provides KZG commitments and proofs directly, avoiding unnecessary computation.
1 parent a65b475 commit d41cfb5

File tree

3 files changed

+38
-31
lines changed

3 files changed

+38
-31
lines changed

archiver/service/archiver.go

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,9 @@ func (a *Archiver) Stop(ctx context.Context) error {
125125
// perform any validation of the blobs, it assumes a trusted beacon node. See:
126126
// https://github.com/base/blob-archiver/issues/4.
127127
//
128-
// The function prefers the /eth/v1/beacon/blobs endpoint but falls back to /eth/v1/beacon/blob_sidecars
129-
// if the blobs endpoint fails.
128+
// The function prefers the /eth/v1/beacon/blob_sidecars endpoint but falls back to /eth/v1/beacon/blobs
129+
// if the blob sidecars endpoint fails. This avoids recomputing KZG commitments and proofs when they're
130+
// available from the beacon node.
130131
func (a *Archiver) persistBlobsForBlockToS3(ctx context.Context, blockIdentifier string, overwrite bool) (*v1.BeaconBlockHeader, bool, error) {
131132
currentHeader, err := a.beaconClient.BeaconBlockHeader(ctx, &api.BeaconBlockHeaderOpts{
132133
Block: blockIdentifier,
@@ -148,38 +149,44 @@ func (a *Archiver) persistBlobsForBlockToS3(ctx context.Context, blockIdentifier
148149
return currentHeader.Data, true, nil
149150
}
150151

151-
// Try the new blobs endpoint first
152+
// Try the blob sidecars endpoint first to get commitments and proofs directly
152153
var blobSidecarData []*deneb.BlobSidecar
153-
blobs, err := a.beaconClient.Blobs(ctx, &api.BlobsOpts{
154+
blobSidecarsResp, err := a.beaconClient.BlobSidecars(ctx, &api.BlobSidecarsOpts{
154155
Block: currentHeader.Data.Root.String(),
155156
})
156157

157-
if err == nil && blobs != nil && blobs.Data != nil && len(blobs.Data) > 0 {
158-
// Successfully fetched blobs, compute commitments and proofs from blob data
159-
a.log.Debug("fetched blobs from blobs endpoint, computing KZG commitments and proofs", "count", len(blobs.Data))
160-
161-
var err error
162-
blobSidecarData, err = blobsToSidecars(blobs.Data, currentHeader.Data)
163-
if err != nil {
164-
a.log.Error("failed to compute KZG commitments and proofs for blobs", "err", err)
165-
return nil, false, err
166-
}
158+
if err == nil && blobSidecarsResp != nil && blobSidecarsResp.Data != nil {
159+
// Successfully fetched blob sidecars with KZG commitments and proofs
160+
a.log.Debug("fetched blob sidecars from blob_sidecars endpoint", "count", len(blobSidecarsResp.Data))
161+
blobSidecarData = blobSidecarsResp.Data
167162
} else {
168-
// Fall back to blob sidecars endpoint
163+
// Fall back to blobs endpoint and compute commitments and proofs
169164
if err != nil {
170-
a.log.Debug("blobs endpoint failed, falling back to blob sidecars", "err", err)
165+
a.log.Debug("blob sidecars endpoint failed, falling back to blobs", "err", err)
171166
}
172167

173-
blobSidecarsResp, fallbackErr := a.beaconClient.BlobSidecars(ctx, &api.BlobSidecarsOpts{
168+
blobs, fallbackErr := a.beaconClient.Blobs(ctx, &api.BlobsOpts{
174169
Block: currentHeader.Data.Root.String(),
175170
})
176171

177172
if fallbackErr != nil {
178-
a.log.Error("failed to fetch blob sidecars", "err", fallbackErr)
173+
a.log.Error("failed to fetch blobs", "err", fallbackErr)
179174
return nil, false, fallbackErr
180175
}
181176

182-
blobSidecarData = blobSidecarsResp.Data
177+
if blobs == nil || blobs.Data == nil {
178+
a.log.Error("blobs endpoint returned nil data")
179+
return nil, false, errors.New("blobs endpoint returned nil data")
180+
}
181+
182+
a.log.Debug("fetched blobs from blobs endpoint, computing KZG commitments and proofs", "count", len(blobs.Data))
183+
184+
var computeErr error
185+
blobSidecarData, computeErr = blobsToSidecars(blobs.Data, currentHeader.Data)
186+
if computeErr != nil {
187+
a.log.Error("failed to compute KZG commitments and proofs for blobs", "err", computeErr)
188+
return nil, false, computeErr
189+
}
183190
}
184191

185192
a.log.Debug("fetched blob sidecars", "count", len(blobSidecarData))

archiver/service/archiver_test.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -475,14 +475,14 @@ func TestArchiver_RearchiveRange(t *testing.T) {
475475
require.Equal(t, fs.ReadOrFail(t, blobtest.Three).BlobSidecars.Data, beacon.SidecarsByBlock[blobtest.Three.String()])
476476
}
477477

478-
func TestArchiver_FetchBlobs_FallbackToSidecars(t *testing.T) {
478+
func TestArchiver_FetchBlobSidecars_Success(t *testing.T) {
479479
beacon := beacontest.NewDefaultStubBeaconClient(t)
480-
beacon.FailBlobs = true // Make blobs endpoint fail
480+
// FailSidecars = false (default) - blob sidecars endpoint should succeed
481481
svc, fs := setup(t, beacon)
482482

483483
fs.CheckNotExistsOrFail(t, blobtest.One)
484484

485-
// Should fall back to blob sidecars endpoint
485+
// Should use blob sidecars endpoint successfully
486486
header, alreadyExists, err := svc.persistBlobsForBlockToS3(context.Background(), blobtest.One.String(), false)
487487
require.False(t, alreadyExists)
488488
require.NoError(t, err)
@@ -493,14 +493,14 @@ func TestArchiver_FetchBlobs_FallbackToSidecars(t *testing.T) {
493493
require.Equal(t, len(beacon.SidecarsByBlock[blobtest.One.String()]), len(stored.BlobSidecars.Data))
494494
}
495495

496-
func TestArchiver_FetchBlobs_Success(t *testing.T) {
496+
func TestArchiver_FetchBlobs_FallbackToBlobs(t *testing.T) {
497497
beacon := beacontest.NewDefaultStubBeaconClient(t)
498-
// FailBlobs = false (default) - blobs endpoint should succeed
498+
beacon.FailSidecars = true // Make blob sidecars endpoint fail
499499
svc, fs := setup(t, beacon)
500500

501501
fs.CheckNotExistsOrFail(t, blobtest.Two)
502502

503-
// Should use blobs endpoint successfully
503+
// Should fall back to blobs endpoint and compute KZG commitments/proofs
504504
header, alreadyExists, err := svc.persistBlobsForBlockToS3(context.Background(), blobtest.Two.String(), false)
505505
require.False(t, alreadyExists)
506506
require.NoError(t, err)
@@ -511,7 +511,7 @@ func TestArchiver_FetchBlobs_Success(t *testing.T) {
511511
// Should have stored the correct number of blobs
512512
require.Equal(t, len(beacon.SidecarsByBlock[blobtest.Two.String()]), len(stored.BlobSidecars.Data))
513513

514-
// Verify that KZG commitments and proofs were derived correctly
514+
// Verify that KZG commitments and proofs were computed correctly from blob data
515515
for i, storedSidecar := range stored.BlobSidecars.Data {
516516
originalSidecar := beacon.SidecarsByBlock[blobtest.Two.String()][i]
517517
// The blob data should match

common/beacon/beacontest/stub.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import (
1717
type StubBeaconClient struct {
1818
Headers map[string]*v1.BeaconBlockHeader
1919
SidecarsByBlock map[string][]*deneb.BlobSidecar
20-
FailBlobs bool
20+
FailSidecars bool
2121
}
2222

2323
func (s *StubBeaconClient) BeaconBlockHeader(ctx context.Context, opts *api.BeaconBlockHeaderOpts) (*api.Response[*v1.BeaconBlockHeader], error) {
@@ -31,6 +31,10 @@ func (s *StubBeaconClient) BeaconBlockHeader(ctx context.Context, opts *api.Beac
3131
}
3232

3333
func (s *StubBeaconClient) BlobSidecars(ctx context.Context, opts *api.BlobSidecarsOpts) (*api.Response[[]*deneb.BlobSidecar], error) {
34+
if s.FailSidecars {
35+
return nil, fmt.Errorf("blob sidecars endpoint unavailable")
36+
}
37+
3438
blobs, found := s.SidecarsByBlock[opts.Block]
3539
if !found {
3640
return nil, fmt.Errorf("block not found")
@@ -42,10 +46,6 @@ func (s *StubBeaconClient) BlobSidecars(ctx context.Context, opts *api.BlobSidec
4246

4347
// Blobs implements the BlobsProvider interface, converting sidecars to blobs
4448
func (s *StubBeaconClient) Blobs(ctx context.Context, opts *api.BlobsOpts) (*api.Response[v1.Blobs], error) {
45-
if s.FailBlobs {
46-
return nil, fmt.Errorf("blobs endpoint unavailable")
47-
}
48-
4949
sidecars, found := s.SidecarsByBlock[opts.Block]
5050
if !found {
5151
return nil, fmt.Errorf("block not found")

0 commit comments

Comments
 (0)