Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 75 additions & 4 deletions node-api/handlers/beacon/blob_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,10 @@ func TestGetBlobSidecars(t *testing.T) {
name string
inputs func() beacontypes.GetBlobSidecarsRequest
setMockExpectations func(*testing.T, *mocks.Backend)
check func(t *testing.T, res any, err error)
check func(t *testing.T, backend *mocks.Backend, res any, err error)
}{
{
name: "success",
name: "success - head",
inputs: func() beacontypes.GetBlobSidecarsRequest {
return beacontypes.GetBlobSidecarsRequest{
BlockIDRequest: handlertypes.BlockIDRequest{
Expand All @@ -88,7 +88,7 @@ func TestGetBlobSidecars(t *testing.T) {
b.EXPECT().GetSyncData().Return(int64(1234), int64(1234))
b.EXPECT().GetBlobSidecarsAtSlot(mock.Anything).Return(testSidecars, nil)
},
check: func(t *testing.T, res any, err error) {
check: func(t *testing.T, _ *mocks.Backend, res any, err error) {
t.Helper()

require.NoError(t, err)
Expand All @@ -100,6 +100,77 @@ func TestGetBlobSidecars(t *testing.T) {
require.Equal(t, beacontypes.SidecarFromConsensus(testSidecars[0]), sr.Data[0])
},
},
{
name: "success - head while syncing",
inputs: func() beacontypes.GetBlobSidecarsRequest {
return beacontypes.GetBlobSidecarsRequest{
BlockIDRequest: handlertypes.BlockIDRequest{
BlockID: utils.StateIDHead,
},
Indices: nil,
}
},
setMockExpectations: func(t *testing.T, b *mocks.Backend) {
t.Helper()

b.EXPECT().GetSyncData().Return(int64(1000), int64(800_000))
b.EXPECT().GetBlobSidecarsAtSlot(math.Slot(1000)).Return(testSidecars, nil)
},
check: func(t *testing.T, _ *mocks.Backend, res any, err error) {
t.Helper()

require.NoError(t, err)
require.NotNil(t, res)
},
},
{
name: "success - explicit slot within DA period",
inputs: func() beacontypes.GetBlobSidecarsRequest {
return beacontypes.GetBlobSidecarsRequest{
BlockIDRequest: handlertypes.BlockIDRequest{
BlockID: "999000",
},
Indices: nil,
}
},
setMockExpectations: func(t *testing.T, b *mocks.Backend) {
t.Helper()

b.EXPECT().GetSyncData().Return(int64(1_000_000), int64(1_000_000))
b.EXPECT().GetBlobSidecarsAtSlot(math.Slot(999_000)).Return(testSidecars, nil)
},
check: func(t *testing.T, _ *mocks.Backend, res any, err error) {
t.Helper()

require.NoError(t, err)
require.NotNil(t, res)
},
},
{
name: "reject - slot outside DA period",
inputs: func() beacontypes.GetBlobSidecarsRequest {
return beacontypes.GetBlobSidecarsRequest{
BlockIDRequest: handlertypes.BlockIDRequest{
BlockID: "212568",
},
Indices: nil,
}
},
setMockExpectations: func(t *testing.T, b *mocks.Backend) {
t.Helper()

b.EXPECT().GetSyncData().Return(int64(1_000_000), int64(1_000_000))
},
check: func(t *testing.T, backend *mocks.Backend, res any, err error) {
t.Helper()

require.Error(t, err)
require.Nil(t, res)
require.ErrorContains(t, err, "not within Data Availability Period")
require.ErrorContains(t, err, "212568")
backend.AssertNumberOfCalls(t, "GetBlobSidecarsAtSlot", 0)
},
},
}

for _, tc := range testCases {
Expand Down Expand Up @@ -130,7 +201,7 @@ func TestGetBlobSidecars(t *testing.T) {
res, err := h.GetBlobSidecars(c)

// finally do checks
tc.check(t, res, err)
tc.check(t, backend, res, err)
})
}
}
23 changes: 13 additions & 10 deletions node-api/handlers/beacon/blobs.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,16 @@ func (h *Handler) GetBlobSidecars(c handlers.Context) (any, error) {
return nil, err
}

headHeight, _ := h.backend.GetSyncData()
if headHeight < 0 {
return nil, errors.New("invalid negative block height")
}

var slot math.Slot
if slotID == utils.Head {
latestHeight, _ := h.backend.GetSyncData()
if latestHeight < 0 {
return nil, errors.New("invalid negative block height")
}
slot = math.Slot(latestHeight)
} else {
switch slotID {
case utils.Head:
slot = math.Slot(headHeight)
default:
slot = math.Slot(slotID) //#nosec: G115 // practically safe
}

Expand All @@ -70,11 +72,12 @@ func (h *Handler) GetBlobSidecars(c handlers.Context) (any, error) {
indices[i] = idx.Unwrap()
}

// Validate the requested slot is within the Data Availability Period.
if !h.cs.WithinDAPeriod(slot, slot) {
// Validate the requested slot is within the DA period (epoch-based WithinDAPeriod,
// same check as FinalizeSidecars). Reference local head, not sync target.
if !h.cs.WithinDAPeriod(slot, math.Slot(headHeight)) {
return nil, fmt.Errorf(
"requested slot (%d) is not within Data Availability Period (previous %d epochs)",
slotID, h.cs.MinEpochsForBlobsSidecarsRequest(),
slot.Unwrap(), h.cs.MinEpochsForBlobsSidecarsRequest(),
)
}

Expand Down