@@ -23,6 +23,7 @@ import (
23
23
"github.com/prysmaticlabs/prysm/v5/testing/assert"
24
24
"github.com/prysmaticlabs/prysm/v5/testing/require"
25
25
"github.com/prysmaticlabs/prysm/v5/testing/util"
26
+ "github.com/prysmaticlabs/prysm/v5/time/slots"
26
27
)
27
28
28
29
func TestSendRequest_SendBeaconBlocksByRangeRequest (t * testing.T ) {
@@ -691,3 +692,122 @@ func TestSeqBlobValid(t *testing.T) {
691
692
})
692
693
}
693
694
}
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
+ }
0 commit comments