Skip to content

Commit 8c4ea85

Browse files
Fix Blobs By Range RPC Handler (#14910)
* Add tests for TestSendBlobsByRangeRequest. Currently not working with sequential blob validation. * Copy Root First * Allow Test For Maximum Amount of Blobs * Fails with the Same error * Fix Last Test Assertion * Add in Fix * Changelog --------- Co-authored-by: Preston Van Loon <preston@pvl.dev>
1 parent 4b43f13 commit 8c4ea85

File tree

3 files changed

+124
-1
lines changed

3 files changed

+124
-1
lines changed

beacon-chain/sync/rpc_send_request.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ func SendBlobsByRangeRequest(ctx context.Context, tor blockchain.TemporalOracle,
169169
}
170170
defer closeStream(stream, log)
171171

172-
maxBlobsPerBlock := uint64(params.BeaconConfig().MaxBlobsPerBlock(req.StartSlot))
172+
maxBlobsPerBlock := uint64(params.BeaconConfig().MaxBlobsPerBlock(req.StartSlot + primitives.Slot(req.Count)))
173173
max := params.BeaconConfig().MaxRequestBlobSidecars
174174
if slots.ToEpoch(req.StartSlot) >= params.BeaconConfig().ElectraForkEpoch {
175175
max = params.BeaconConfig().MaxRequestBlobSidecarsElectra

beacon-chain/sync/rpc_send_request_test.go

+120
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/prysmaticlabs/prysm/v5/testing/assert"
2424
"github.com/prysmaticlabs/prysm/v5/testing/require"
2525
"github.com/prysmaticlabs/prysm/v5/testing/util"
26+
"github.com/prysmaticlabs/prysm/v5/time/slots"
2627
)
2728

2829
func TestSendRequest_SendBeaconBlocksByRangeRequest(t *testing.T) {
@@ -691,3 +692,122 @@ func TestSeqBlobValid(t *testing.T) {
691692
})
692693
}
693694
}
695+
696+
func TestSendBlobsByRangeRequest(t *testing.T) {
697+
topic := fmt.Sprintf("%s/ssz_snappy", p2p.RPCBlobSidecarsByRangeTopicV1)
698+
ctx := context.Background()
699+
700+
t.Run("single blob - Deneb", func(t *testing.T) {
701+
// Setup genesis such that we are currently in deneb.
702+
s := uint64(slots.UnsafeEpochStart(params.BeaconConfig().DenebForkEpoch)) * params.BeaconConfig().SecondsPerSlot
703+
clock := startup.NewClock(time.Now().Add(-time.Second*time.Duration(s)), [32]byte{})
704+
ctxByte, err := ContextByteVersionsForValRoot(clock.GenesisValidatorsRoot())
705+
require.NoError(t, err)
706+
// Setup peers
707+
p1 := p2ptest.NewTestP2P(t)
708+
p2 := p2ptest.NewTestP2P(t)
709+
p1.Connect(p2)
710+
// Set current slot to a deneb slot.
711+
slot := slots.UnsafeEpochStart(params.BeaconConfig().DenebForkEpoch + 1)
712+
// Create a simple handler that will return a valid response.
713+
p2.SetStreamHandler(topic, func(stream network.Stream) {
714+
defer func() {
715+
assert.NoError(t, stream.Close())
716+
}()
717+
718+
req := &ethpb.BlobSidecarsByRangeRequest{}
719+
assert.NoError(t, p2.Encoding().DecodeWithMaxLength(stream, req))
720+
assert.Equal(t, slot, req.StartSlot)
721+
assert.Equal(t, uint64(1), req.Count)
722+
723+
// Create a sequential set of blobs with the appropriate header information.
724+
var prevRoot [32]byte
725+
for i := req.StartSlot; i < req.StartSlot+primitives.Slot(req.Count); i++ {
726+
b := util.HydrateBlobSidecar(&ethpb.BlobSidecar{})
727+
b.SignedBlockHeader.Header.Slot = i
728+
b.SignedBlockHeader.Header.ParentRoot = prevRoot[:]
729+
ro, err := blocks.NewROBlob(b)
730+
require.NoError(t, err)
731+
vro := blocks.NewVerifiedROBlob(ro)
732+
prevRoot = vro.BlockRoot()
733+
assert.NoError(t, WriteBlobSidecarChunk(stream, clock, p2.Encoding(), vro))
734+
}
735+
})
736+
req := &ethpb.BlobSidecarsByRangeRequest{
737+
StartSlot: slot,
738+
Count: 1,
739+
}
740+
741+
blobs, err := SendBlobsByRangeRequest(ctx, clock, p1, p2.PeerID(), ctxByte, req)
742+
assert.NoError(t, err)
743+
assert.Equal(t, 1, len(blobs))
744+
})
745+
746+
t.Run("Deneb - Electra epoch boundary crossing", func(t *testing.T) {
747+
cfg := params.BeaconConfig()
748+
cfg.ElectraForkEpoch = cfg.DenebForkEpoch + 1
749+
undo, err := params.SetActiveWithUndo(cfg)
750+
require.NoError(t, err)
751+
defer func() {
752+
require.NoError(t, undo())
753+
}()
754+
// Setup genesis such that we are currently in deneb.
755+
s := uint64(slots.UnsafeEpochStart(params.BeaconConfig().DenebForkEpoch)) * params.BeaconConfig().SecondsPerSlot
756+
clock := startup.NewClock(time.Now().Add(-time.Second*time.Duration(s)), [32]byte{})
757+
ctxByte, err := ContextByteVersionsForValRoot(clock.GenesisValidatorsRoot())
758+
require.NoError(t, err)
759+
// Setup peers
760+
p1 := p2ptest.NewTestP2P(t)
761+
p2 := p2ptest.NewTestP2P(t)
762+
p1.Connect(p2)
763+
// Set current slot to the first slot of the last deneb epoch.
764+
slot := slots.UnsafeEpochStart(params.BeaconConfig().DenebForkEpoch)
765+
// Create a simple handler that will return a valid response.
766+
p2.SetStreamHandler(topic, func(stream network.Stream) {
767+
defer func() {
768+
assert.NoError(t, stream.Close())
769+
}()
770+
771+
req := &ethpb.BlobSidecarsByRangeRequest{}
772+
assert.NoError(t, p2.Encoding().DecodeWithMaxLength(stream, req))
773+
assert.Equal(t, slot, req.StartSlot)
774+
assert.Equal(t, uint64(params.BeaconConfig().SlotsPerEpoch)*3, req.Count)
775+
776+
// Create a sequential set of blobs with the appropriate header information.
777+
var prevRoot [32]byte
778+
for i := req.StartSlot; i < req.StartSlot+primitives.Slot(req.Count); i++ {
779+
maxBlobsForSlot := cfg.MaxBlobsPerBlock(i)
780+
parentRoot := prevRoot
781+
header := util.HydrateSignedBeaconHeader(&ethpb.SignedBeaconBlockHeader{})
782+
header.Header.Slot = i
783+
header.Header.ParentRoot = parentRoot[:]
784+
bRoot, err := header.Header.HashTreeRoot()
785+
require.NoError(t, err)
786+
prevRoot = bRoot
787+
// Send the maximum possible blobs per slot.
788+
for j := 0; j < maxBlobsForSlot; j++ {
789+
b := util.HydrateBlobSidecar(&ethpb.BlobSidecar{})
790+
b.SignedBlockHeader = header
791+
b.Index = uint64(j)
792+
ro, err := blocks.NewROBlob(b)
793+
require.NoError(t, err)
794+
vro := blocks.NewVerifiedROBlob(ro)
795+
assert.NoError(t, WriteBlobSidecarChunk(stream, clock, p2.Encoding(), vro))
796+
}
797+
}
798+
})
799+
req := &ethpb.BlobSidecarsByRangeRequest{
800+
StartSlot: slot,
801+
Count: uint64(params.BeaconConfig().SlotsPerEpoch) * 3,
802+
}
803+
maxDenebBlobs := cfg.MaxBlobsPerBlockAtEpoch(cfg.DenebForkEpoch)
804+
maxElectraBlobs := cfg.MaxBlobsPerBlockAtEpoch(cfg.ElectraForkEpoch)
805+
totalDenebBlobs := primitives.Slot(maxDenebBlobs) * params.BeaconConfig().SlotsPerEpoch
806+
totalElectraBlobs := primitives.Slot(maxElectraBlobs) * 2 * params.BeaconConfig().SlotsPerEpoch
807+
totalExpectedBlobs := totalDenebBlobs + totalElectraBlobs
808+
809+
blobs, err := SendBlobsByRangeRequest(ctx, clock, p1, p2.PeerID(), ctxByte, req)
810+
assert.NoError(t, err)
811+
assert.Equal(t, int(totalExpectedBlobs), len(blobs))
812+
})
813+
}
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
### Fixed
2+
3+
- We now use the correct maximum value when serving blobs for electra blocks.

0 commit comments

Comments
 (0)