@@ -2,6 +2,7 @@ use std::borrow::Borrow;
22use std:: collections:: HashMap ;
33use std:: fmt:: Debug ;
44
5+ use futures:: stream:: { FuturesUnordered , StreamExt } ;
56use starknet_api:: core:: ContractAddress ;
67use starknet_api:: hash:: HashOutput ;
78use starknet_patricia:: db_layout:: { NodeLayout , NodeLayoutFor } ;
@@ -459,3 +460,63 @@ where
459460 }
460461 Ok ( storage_tries)
461462}
463+
464+ // TODO(Nimrod): Remove the `allow(dead_code)` once we use this function.
465+ #[ allow( dead_code) ]
466+ async fn create_storage_tries_concurrently < ' a , Layout : NodeLayoutFor < StarknetStorageValue > > (
467+ storage : & impl Storage ,
468+ actual_storage_updates : & HashMap < ContractAddress , LeafModifications < StarknetStorageValue > > ,
469+ original_contracts_trie_leaves : & HashMap < NodeIndex , ContractState > ,
470+ config : & ReaderConfig ,
471+ storage_tries_sorted_indices : & HashMap < ContractAddress , SortedLeafIndices < ' a > > ,
472+ ) -> ForestResult < HashMap < ContractAddress , OriginalSkeletonTreeImpl < ' a > > >
473+ where
474+ <Layout as NodeLayoutFor < StarknetStorageValue > >:: DbLeaf :
475+ HasStaticPrefix < KeyContext = ContractAddress > ,
476+ {
477+ let mut futures = FuturesUnordered :: new ( ) ;
478+ let mut storage_tries = HashMap :: new ( ) ;
479+
480+ for ( address, updates) in actual_storage_updates {
481+ // Extract data needed for this contract.
482+ let sorted_leaf_indices = * storage_tries_sorted_indices
483+ . get ( address)
484+ . ok_or ( ForestError :: MissingSortedLeafIndices ( * address) ) ?;
485+ let contract_state = original_contracts_trie_leaves
486+ . get ( & contract_address_into_node_index ( address) )
487+ . ok_or ( ForestError :: MissingContractCurrentState ( * address) ) ?;
488+ let trie_config = OriginalSkeletonTrieConfig :: new_for_classes_or_storage_trie (
489+ config. warn_on_trivial_modifications ( ) ,
490+ ) ;
491+
492+ // TODO(Ariel): Change `LeafModifications` in `actual_storage_updates` to be an
493+ // iterator over borrowed data so that the conversion below is costless.
494+ let leaf_modifications: HashMap <
495+ NodeIndex ,
496+ <Layout as NodeLayoutFor < StarknetStorageValue > >:: DbLeaf ,
497+ > = updates. iter ( ) . map ( |( idx, value) | ( * idx, Layout :: DbLeaf :: from ( * value) ) ) . collect ( ) ;
498+
499+ // Create the future - tokio will poll all futures concurrently.
500+ futures. push ( async move {
501+ let original_skeleton = create_original_skeleton_tree :: < Layout :: DbLeaf , Layout > (
502+ storage,
503+ contract_state. storage_root_hash ,
504+ sorted_leaf_indices,
505+ & trie_config,
506+ & leaf_modifications,
507+ None ,
508+ address,
509+ )
510+ . await ?;
511+ Ok :: < _ , ForestError > ( ( address, original_skeleton) )
512+ } ) ;
513+ }
514+
515+ // Collect all results as they complete.
516+ while let Some ( result) = futures. next ( ) . await {
517+ let ( address, original_skeleton) = result?;
518+ storage_tries. insert ( * address, original_skeleton) ;
519+ }
520+
521+ Ok ( storage_tries)
522+ }
0 commit comments