@@ -13,40 +13,61 @@ import (
1313 "github.com/libp2p/go-libp2p/core/network"
1414)
1515
16+ var errInvalidDataColumnIndex = errors .New ("invalid column index" )
17+
18+ func writeDataColumnSidecarsEmptySuccess (s network.Stream ) error {
19+ return nil
20+ }
21+
1622func (c * ConsensusHandlers ) dataColumnSidecarsByRangeHandler (s network.Stream ) error {
1723 curEpoch := c .ethClock .GetCurrentEpoch ()
18- if curEpoch < c .beaconConfig .FuluForkEpoch {
19- return nil
20- }
2124
2225 // Use current epoch's version for decoding (supports Fulu and GLOAS)
2326 version := c .beaconConfig .GetCurrentStateVersion (curEpoch )
2427 req := & cltypes.ColumnSidecarsByRangeRequest {}
2528 if err := ssz_snappy .DecodeAndReadNoForkDigest (s , req , version ); err != nil {
26- return err
29+ return ssz_snappy .EncodeAndWrite (s , & emptyString {}, InvalidRequestPrefix )
30+ }
31+ if curEpoch < c .beaconConfig .FuluForkEpoch {
32+ return writeDataColumnSidecarsEmptySuccess (s )
2733 }
2834
2935 // check params.
3036 var (
31- endSlot = req . StartSlot + req . Count
32- startSlot = max ( req .StartSlot , c . beaconConfig . FuluForkEpoch * c . beaconConfig . SlotsPerEpoch )
37+ fuluStartSlot = c . beaconConfig . FuluForkEpoch * c . beaconConfig . SlotsPerEpoch
38+ endSlot = req .StartSlot + req . Count
3339 )
34- if endSlot - startSlot > c .beaconConfig .MinEpochsForDataColumnSidecarsRequests * c .beaconConfig .SlotsPerEpoch {
35- return errors .New ("request range is too large" )
40+ if endSlot < req .StartSlot {
41+ return ssz_snappy .EncodeAndWrite (s , & emptyString {}, InvalidRequestPrefix )
42+ }
43+ if req .Columns .Length () > int (c .beaconConfig .NumberOfColumns ) {
44+ return ssz_snappy .EncodeAndWrite (s , & emptyString {}, InvalidRequestPrefix )
3645 }
37- solid .RangeErr (req .Columns , func (index int , columnIndex uint64 , length int ) error {
46+ if err := solid .RangeErr (req .Columns , func (index int , columnIndex uint64 , length int ) error {
3847 if columnIndex >= c .beaconConfig .NumberOfColumns {
39- return errors . New ( "invalid column index" )
48+ return errInvalidDataColumnIndex
4049 }
4150 return nil
42- })
51+ }); err != nil {
52+ return ssz_snappy .EncodeAndWrite (s , & emptyString {}, InvalidRequestPrefix )
53+ }
54+ if req .Count == 0 || req .Columns .Length () == 0 || endSlot <= fuluStartSlot {
55+ return writeDataColumnSidecarsEmptySuccess (s )
56+ }
57+ startSlot := max (req .StartSlot , fuluStartSlot )
58+ if endSlot - startSlot > c .beaconConfig .MinEpochsForDataColumnSidecarsRequests * c .beaconConfig .SlotsPerEpoch {
59+ return ssz_snappy .EncodeAndWrite (s , & emptyString {}, InvalidRequestPrefix )
60+ }
4361
4462 // Consume additional rate-limit tokens: slots × columns per slot, capped at config max.
45- if cost := min ( int (req .Count ) * req . Columns .Length (), int ( c .beaconConfig .MaxRequestDataColumnSidecars )) - 1 ; ! c .consumeRateLimit (s , cost ) {
63+ if cost := dataColumnSidecarsRequestCost ( endSlot - startSlot , uint64 (req .Columns .Length ()), c .beaconConfig .MaxRequestDataColumnSidecars ); ! c .consumeRateLimit (s , cost ) {
4664 return nil
4765 }
4866
4967 curSlot := c .ethClock .GetCurrentSlot ()
68+ if startSlot > curSlot {
69+ return writeDataColumnSidecarsEmptySuccess (s )
70+ }
5071
5172 tx , err := c .indiciesDB .BeginRo (c .ctx )
5273 if err != nil {
@@ -55,6 +76,7 @@ func (c *ConsensusHandlers) dataColumnSidecarsByRangeHandler(s network.Stream) e
5576 defer tx .Rollback ()
5677
5778 count := 0
79+ var responseErr error
5880 for slot := startSlot ; slot < endSlot ; slot ++ {
5981 if slot > curSlot {
6082 // slot is in the future
@@ -84,6 +106,7 @@ func (c *ConsensusHandlers) dataColumnSidecarsByRangeHandler(s network.Stream) e
84106 exists , err := c .dataColumnStorage .ColumnSidecarExists (c .ctx , slot , blockRoot , int64 (columnIndex ))
85107 if err != nil {
86108 log .Debug ("failed to check if data column sidecar exists" , "error" , err )
109+ responseErr = err
87110 return false
88111 }
89112 if ! exists {
@@ -94,56 +117,83 @@ func (c *ConsensusHandlers) dataColumnSidecarsByRangeHandler(s network.Stream) e
94117 forkDigest , err := c .ethClock .ComputeForkDigest (slot / c .beaconConfig .SlotsPerEpoch )
95118 if err != nil {
96119 log .Debug ("failed to compute fork digest" , "error" , err )
120+ responseErr = err
97121 return false
98122 }
99123 if _ , err := s .Write ([]byte {SuccessfulResponsePrefix }); err != nil {
100124 log .Debug ("failed to write success byte" , "error" , err )
125+ responseErr = err
101126 return false
102127 }
103128
104129 if _ , err := s .Write (forkDigest [:]); err != nil {
105130 log .Debug ("failed to write fork digest" , "error" , err )
131+ responseErr = err
106132 return false
107133 }
108134
109135 if err := c .dataColumnStorage .WriteStream (s , slot , blockRoot , columnIndex ); err != nil {
110136 log .Debug ("failed to write stream data column sidecar" , "error" , err )
137+ responseErr = err
111138 return false
112139 }
113140 count ++
114141 return true
115142 })
143+ if responseErr != nil {
144+ break
145+ }
116146 if count >= int (c .beaconConfig .MaxRequestDataColumnSidecars ) {
117147 // max number of sidecars reached
118148 break
119149 }
120150 }
121-
151+ if responseErr != nil {
152+ return responseErr
153+ }
154+ if count == 0 {
155+ return writeDataColumnSidecarsEmptySuccess (s )
156+ }
122157 return nil
123158}
124159
125160func (c * ConsensusHandlers ) dataColumnSidecarsByRootHandler (s network.Stream ) error {
126161 curEpoch := c .ethClock .GetCurrentEpoch ()
127- if curEpoch < c .beaconConfig .FuluForkEpoch {
128- return nil
129- }
130162
131163 // Use current epoch's version for decoding (supports Fulu and GLOAS)
132164 version := c .beaconConfig .GetCurrentStateVersion (curEpoch )
133165 req := solid.NewDynamicListSSZ [* cltypes.DataColumnsByRootIdentifier ](int (c .beaconConfig .MaxRequestBlocksDeneb ))
134166 if err := ssz_snappy .DecodeAndReadNoForkDigest (s , req , version ); err != nil {
135- return err
167+ return ssz_snappy . EncodeAndWrite ( s , & emptyString {}, InvalidRequestPrefix )
136168 }
137169 if req .Len () > int (c .beaconConfig .MaxRequestBlocksDeneb ) {
138- return errors . New ( "request is too large" )
170+ return ssz_snappy . EncodeAndWrite ( s , & emptyString {}, InvalidRequestPrefix )
139171 }
140172
141173 // Consume additional rate-limit tokens: sum of column counts across all roots.
142174 totalColumns := 0
143175 for i := 0 ; i < req .Len (); i ++ {
144- totalColumns += req .Get (i ).Columns .Length ()
176+ columns := req .Get (i ).Columns
177+ if columns .Length () > int (c .beaconConfig .NumberOfColumns ) {
178+ return ssz_snappy .EncodeAndWrite (s , & emptyString {}, InvalidRequestPrefix )
179+ }
180+ if err := solid .RangeErr (columns , func (index int , columnIndex uint64 , length int ) error {
181+ if columnIndex >= c .beaconConfig .NumberOfColumns {
182+ return errInvalidDataColumnIndex
183+ }
184+ return nil
185+ }); err != nil {
186+ return ssz_snappy .EncodeAndWrite (s , & emptyString {}, InvalidRequestPrefix )
187+ }
188+ totalColumns += columns .Length ()
189+ }
190+ if curEpoch < c .beaconConfig .FuluForkEpoch {
191+ return ssz_snappy .EncodeAndWrite (s , & emptyString {}, ResourceUnavailablePrefix )
145192 }
146- if cost := min (totalColumns , int (c .beaconConfig .MaxRequestDataColumnSidecars )) - 1 ; ! c .consumeRateLimit (s , cost ) {
193+ if totalColumns == 0 {
194+ return writeDataColumnSidecarsEmptySuccess (s )
195+ }
196+ if cost := dataColumnSidecarsRequestCost (1 , uint64 (totalColumns ), c .beaconConfig .MaxRequestDataColumnSidecars ); ! c .consumeRateLimit (s , cost ) {
147197 return nil
148198 }
149199
@@ -157,6 +207,7 @@ func (c *ConsensusHandlers) dataColumnSidecarsByRootHandler(s network.Stream) er
157207 defer tx .Rollback ()
158208
159209 count := 0
210+ var responseErr error
160211 for i := 0 ; i < req .Len (); i ++ {
161212 id := req .Get (i )
162213 blockRoot := id .BlockRoot
@@ -188,14 +239,11 @@ func (c *ConsensusHandlers) dataColumnSidecarsByRootHandler(s network.Stream) er
188239 // max number of sidecars reached
189240 return false
190241 }
191- if columnIndex >= c .beaconConfig .NumberOfColumns {
192- // skip invalid column index
193- return true
194- }
195242
196243 exists , err := c .dataColumnStorage .ColumnSidecarExists (c .ctx , * slot , blockRoot , int64 (columnIndex ))
197244 if err != nil {
198245 log .Debug ("failed to check if data column sidecar exists" , "error" , err )
246+ responseErr = err
199247 return false
200248 }
201249 if ! exists {
@@ -206,25 +254,52 @@ func (c *ConsensusHandlers) dataColumnSidecarsByRootHandler(s network.Stream) er
206254 forkDigest , err := c .ethClock .ComputeForkDigest (* slot / c .beaconConfig .SlotsPerEpoch )
207255 if err != nil {
208256 log .Debug ("failed to compute fork digest" , "error" , err )
257+ responseErr = err
209258 return false
210259 }
211260 if _ , err := s .Write ([]byte {SuccessfulResponsePrefix }); err != nil {
212261 log .Debug ("failed to write success byte" , "error" , err )
262+ responseErr = err
213263 return false
214264 }
215265
216266 if _ , err := s .Write (forkDigest [:]); err != nil {
217267 log .Debug ("failed to write fork digest" , "error" , err )
268+ responseErr = err
218269 return false
219270 }
220271
221272 if err := c .dataColumnStorage .WriteStream (s , * slot , blockRoot , columnIndex ); err != nil {
222273 log .Debug ("failed to write stream data column sidecar" , "error" , err )
274+ responseErr = err
223275 return false
224276 }
225277 count ++
226278 return true
227279 })
280+ if responseErr != nil {
281+ break
282+ }
283+ }
284+ if responseErr != nil {
285+ return responseErr
286+ }
287+ if count == 0 {
288+ return ssz_snappy .EncodeAndWrite (s , & emptyString {}, ResourceUnavailablePrefix )
228289 }
229290 return nil
230291}
292+
293+ func dataColumnSidecarsRequestCost (slots , columns , maxSidecars uint64 ) int {
294+ if slots == 0 || columns == 0 || maxSidecars == 0 {
295+ return 0
296+ }
297+ if slots > maxSidecars / columns {
298+ return int (maxSidecars ) - 1
299+ }
300+ sidecars := slots * columns
301+ if sidecars > maxSidecars {
302+ sidecars = maxSidecars
303+ }
304+ return int (sidecars ) - 1
305+ }
0 commit comments