@@ -166,7 +166,7 @@ where
166166 Ok ( blobs) = self . get_blobs_from_explorer( tx_hash) => {
167167 Ok ( blobs)
168168 }
169- Ok ( blobs) = self . get_blobs_from_cl ( slot, versioned_hashes) => {
169+ Ok ( blobs) = self . get_blobs_from_cl_exact ( slot, versioned_hashes) => {
170170 Ok ( blobs)
171171 }
172172 Ok ( blobs) = self . get_blobs_from_pylon( tx_hash) => {
@@ -207,8 +207,13 @@ where
207207 . map_err ( Into :: into)
208208 }
209209
210- /// Queries the connected consensus client for the blob transaction
210+ /// Queries the consensus client for blobs at a given slot, filtering by
211+ /// versioned hashes (best-effort).
212+ ///
213+ /// This method returns whatever blobs the consensus client provides, even
214+ /// if fewer than requested. Use this when partial blob results are acceptable.
211215 #[ instrument( skip_all) ]
216+ #[ allow( dead_code) ]
212217 async fn get_blobs_from_cl (
213218 & self ,
214219 slot : usize ,
@@ -218,6 +223,36 @@ where
218223 return Err ( FetchError :: ConsensusClientUrlNotSet ) ;
219224 } ;
220225
226+ let mut url =
227+ url. join ( & format ! ( "/eth/v1/beacon/blobs/{slot}" ) ) . map_err ( FetchError :: UrlParse ) ?;
228+
229+ let versioned_hashes =
230+ versioned_hashes. iter ( ) . map ( |hash| hash. to_string ( ) ) . collect :: < Vec < _ > > ( ) . join ( "," ) ;
231+ url. query_pairs_mut ( ) . append_pair ( "versioned_hashes" , & versioned_hashes) ;
232+
233+ let response = self . client . get ( url) . header ( "accept" , "application/json" ) . send ( ) . await ?;
234+
235+ let response: GetBlobsResponse = response. json ( ) . await ?;
236+
237+ Ok ( Arc :: new ( response. data ) . into ( ) )
238+ }
239+
240+ /// Queries the consensus client for blobs at a given slot, filtering by
241+ /// versioned hashes (exact match required).
242+ ///
243+ /// This method enforces that the consensus client returns exactly the
244+ /// number of blobs requested. If the count doesn't match, returns
245+ /// [`FetchError::BlobCountMismatch`].
246+ #[ instrument( skip_all) ]
247+ async fn get_blobs_from_cl_exact (
248+ & self ,
249+ slot : usize ,
250+ versioned_hashes : & [ B256 ] ,
251+ ) -> FetchResult < Blobs > {
252+ let Some ( url) = & self . cl_url else {
253+ return Err ( FetchError :: ConsensusClientUrlNotSet ) ;
254+ } ;
255+
221256 let mut url =
222257 url. join ( & format ! ( "/eth/v1/beacon/blobs/{slot}" ) ) . map_err ( FetchError :: UrlParse ) ?;
223258
0 commit comments