@@ -225,11 +225,10 @@ where
225225 pub ( super ) async fn process_validated_block (
226226 & mut self ,
227227 certificate : ValidatedBlockCertificate ,
228- blobs : & [ Blob ] ,
229228 ) -> Result < ( ChainInfoResponse , NetworkActions , bool ) , WorkerError > {
230229 ChainWorkerStateWithAttemptedChanges :: new ( self )
231230 . await
232- . process_validated_block ( certificate, blobs )
231+ . process_validated_block ( certificate)
233232 . await
234233 }
235234
@@ -300,6 +299,17 @@ where
300299 maybe_blob. ok_or_else ( || WorkerError :: BlobsNotFound ( vec ! [ blob_id] ) )
301300 }
302301
302+ /// Adds the blob to pending blocks or validated block certificates that are missing it.
303+ pub ( super ) async fn handle_pending_blob (
304+ & mut self ,
305+ blob : Blob ,
306+ ) -> Result < ChainInfoResponse , WorkerError > {
307+ ChainWorkerStateWithAttemptedChanges :: new ( & mut * self )
308+ . await
309+ . handle_pending_blob ( blob)
310+ . await
311+ }
312+
303313 /// Ensures that the current chain is active, returning an error otherwise.
304314 fn ensure_is_active ( & mut self ) -> Result < ( ) , WorkerError > {
305315 if !self . knows_chain_is_active {
@@ -309,61 +319,57 @@ where
309319 Ok ( ( ) )
310320 }
311321
312- /// Returns an error if unrelated blobs were provided.
313- fn check_for_unneeded_blobs (
314- & self ,
315- required_blob_ids : & HashSet < BlobId > ,
316- blobs : & [ Blob ] ,
317- ) -> Result < ( ) , WorkerError > {
318- // Find all certificates containing blobs used when executing this block.
319- for blob in blobs {
320- let blob_id = blob. id ( ) ;
321- ensure ! (
322- required_blob_ids. contains( & blob_id) ,
323- WorkerError :: UnneededBlob { blob_id }
324- ) ;
325- }
326-
327- Ok ( ( ) )
328- }
329-
330322 /// Returns the blobs required by the given executed block. The ones that are not passed in
331323 /// are read from the chain manager or from storage.
332324 async fn get_required_blobs (
333325 & self ,
334326 executed_block : & ExecutedBlock ,
335327 blobs : & [ Blob ] ,
336328 ) -> Result < BTreeMap < BlobId , Blob > , WorkerError > {
337- let mut blob_ids = executed_block. required_blob_ids ( ) ;
338- let mut found_blobs = BTreeMap :: new ( ) ;
329+ let maybe_blobs = self . maybe_get_required_blobs ( executed_block, blobs) . await ?;
330+ let not_found_blob_ids = missing_blob_ids ( & maybe_blobs) ;
331+ ensure ! (
332+ not_found_blob_ids. is_empty( ) ,
333+ WorkerError :: BlobsNotFound ( not_found_blob_ids)
334+ ) ;
335+ Ok ( maybe_blobs
336+ . into_iter ( )
337+ . filter_map ( |( blob_id, maybe_blob) | Some ( ( blob_id, maybe_blob?) ) )
338+ . collect ( ) )
339+ }
339340
340- for blob in blobs {
341- if blob_ids. remove ( & blob. id ( ) ) {
342- found_blobs. insert ( blob. id ( ) , blob. clone ( ) ) ;
341+ /// Returns the blobs required by the given executed block. The ones that are not passed in
342+ /// are read from the chain manager or from storage.
343+ async fn maybe_get_required_blobs (
344+ & self ,
345+ executed_block : & ExecutedBlock ,
346+ provided_blobs : & [ Blob ] ,
347+ ) -> Result < BTreeMap < BlobId , Option < Blob > > , WorkerError > {
348+ let required_blob_ids = executed_block. required_blob_ids ( ) . into_iter ( ) ;
349+ let mut maybe_blobs = BTreeMap :: from_iter ( required_blob_ids. map ( |blob_id| ( blob_id, None ) ) ) ;
350+
351+ for blob in provided_blobs {
352+ if let Some ( maybe_blob) = maybe_blobs. get_mut ( & blob. id ( ) ) {
353+ * maybe_blob = Some ( blob. clone ( ) ) ;
343354 }
344355 }
345- let mut missing_blob_ids = Vec :: new ( ) ;
346- for blob_id in blob_ids {
347- if let Some ( blob) = self . chain . manager . pending_blob ( & blob_id) . await ? {
348- found_blobs. insert ( blob_id, blob) ;
349- } else {
350- missing_blob_ids. push ( blob_id) ;
356+ for ( blob_id, maybe_blob) in & mut maybe_blobs {
357+ if maybe_blob. is_some ( ) {
358+ continue ;
359+ }
360+ if let Some ( blob) = self . chain . manager . pending_blob ( blob_id) . await ? {
361+ * maybe_blob = Some ( blob) ;
362+ } else if let Some ( Some ( blob) ) = self . chain . pending_validated_blobs . get ( blob_id) . await ?
363+ {
364+ * maybe_blob = Some ( blob) ;
351365 }
352366 }
367+ let missing_blob_ids = missing_blob_ids ( & maybe_blobs) ;
353368 let blobs_from_storage = self . storage . read_blobs ( & missing_blob_ids) . await ?;
354- let mut not_found_blob_ids = Vec :: new ( ) ;
355369 for ( blob_id, maybe_blob) in missing_blob_ids. into_iter ( ) . zip ( blobs_from_storage) {
356- if let Some ( blob) = maybe_blob {
357- found_blobs. insert ( blob_id, blob) ;
358- } else {
359- not_found_blob_ids. push ( blob_id) ;
360- }
370+ maybe_blobs. insert ( blob_id, maybe_blob) ;
361371 }
362- ensure ! (
363- not_found_blob_ids. is_empty( ) ,
364- WorkerError :: BlobsNotFound ( not_found_blob_ids)
365- ) ;
366- Ok ( found_blobs)
372+ Ok ( maybe_blobs)
367373 }
368374
369375 /// Adds any newly created chains to the set of `tracked_chains`, if the parent chain is
@@ -542,6 +548,15 @@ where
542548 }
543549}
544550
551+ /// Returns the keys whose value is `None`.
552+ fn missing_blob_ids ( maybe_blobs : & BTreeMap < BlobId , Option < Blob > > ) -> Vec < BlobId > {
553+ maybe_blobs
554+ . iter ( )
555+ . filter ( |( _, maybe_blob) | maybe_blob. is_none ( ) )
556+ . map ( |( chain_id, _) | * chain_id)
557+ . collect ( )
558+ }
559+
545560/// Returns an error if the block is not at the expected epoch.
546561fn check_block_epoch ( chain_epoch : Epoch , block : & Block ) -> Result < ( ) , WorkerError > {
547562 ensure ! (
0 commit comments