@@ -45,6 +45,7 @@ use tracing::warn;
4545
4646use crate :: block_committer:: input:: {
4747 contract_address_into_node_index,
48+ try_node_index_into_contract_address,
4849 ReaderConfig ,
4950 StarknetStorageValue ,
5051} ;
@@ -851,7 +852,6 @@ where
851852}
852853
853854/// Storage task for fetching Patricia paths in a single storage trie.
854- #[ expect( dead_code) ]
855855struct StoragePathsReadTask < ' indices , Layout : NodeLayoutFor < StarknetStorageValue > > {
856856 address : ContractAddress ,
857857 storage_root_hash : HashOutput ,
@@ -925,6 +925,127 @@ where
925925 storage. gather ( tasks) . await . into_iter ( ) . collect ( )
926926}
927927
928+ /// Fetches Patricia proofs for the storage tries. If the storage has a [GatherableStorage] version,
929+ /// then the paths are fetched concurrently. Otherwise, they are fetched sequentially.
930+ #[ allow( dead_code) ]
931+ pub ( crate ) async fn fetch_contract_storage_paths < StorageLayout , ContractLeaf > (
932+ storage : & mut impl ReadOnlyStorage ,
933+ contract_storage_sorted_leaf_indices : & HashMap < NodeIndex , SortedLeafIndices < ' _ > > ,
934+ contract_leaves : & HashMap < NodeIndex , ContractLeaf > ,
935+ ) -> TraversalResult < HashMap < ContractAddress , PreimageMap > >
936+ where
937+ StorageLayout : NodeLayoutFor < StarknetStorageValue > + Send + ' static ,
938+ <StorageLayout as NodeLayoutFor < StarknetStorageValue > >:: DbLeaf :
939+ HasStaticPrefix < KeyContext = ContractAddress > ,
940+ ContractLeaf : AsRef < ContractState > ,
941+ {
942+ if let Some ( gatherable_storage) = storage. as_gatherable_storage ( ) {
943+ return fetch_contract_storage_paths_concurrently :: < _ , StorageLayout , ContractLeaf > (
944+ gatherable_storage,
945+ contract_storage_sorted_leaf_indices,
946+ contract_leaves,
947+ )
948+ . await ;
949+ }
950+ fetch_contract_storage_paths_sequentially :: < StorageLayout , ContractLeaf > (
951+ storage,
952+ contract_storage_sorted_leaf_indices,
953+ contract_leaves,
954+ )
955+ . await
956+ }
957+
958+ /// Returns the contract address and storage root hash for the given leaf index, if the contract
959+ /// exists in the contracts trie.
960+ ///
961+ /// The contract address might not exist in the contracts trie in the following cases:
962+ /// 1. We are looking at the previous tree and the contract is new.
963+ /// 2. We are looking at the new tree and the contract is deleted (revert).
964+ /// In either case, the storage trie of this contract is empty, so there is nothing to
965+ /// prove regarding the contract storage.
966+ pub ( crate ) fn get_address_and_storage_root < ContractLeaf : AsRef < ContractState > > (
967+ idx : & NodeIndex ,
968+ contract_leaves : & HashMap < NodeIndex , ContractLeaf > ,
969+ ) -> Option < ( ContractAddress , HashOutput ) > {
970+ let contract_address = try_node_index_into_contract_address ( idx) . unwrap_or_else ( |_| {
971+ panic ! (
972+ "Converting leaf NodeIndex to ContractAddress should succeed; failed to convert \
973+ {idx:?}."
974+ )
975+ } ) ;
976+ let storage_root_hash = contract_leaves. get ( idx) . map ( |leaf| leaf. as_ref ( ) . storage_root_hash ) ?;
977+ Some ( ( contract_address, storage_root_hash) )
978+ }
979+
980+ /// Sequentially fetches Patricia proofs for the storage tries.
981+ #[ allow( dead_code) ]
982+ async fn fetch_contract_storage_paths_sequentially < StorageLayout , ContractLeaf > (
983+ storage : & mut impl ReadOnlyStorage ,
984+ contract_storage_sorted_leaf_indices : & HashMap < NodeIndex , SortedLeafIndices < ' _ > > ,
985+ contract_leaves : & HashMap < NodeIndex , ContractLeaf > ,
986+ ) -> TraversalResult < HashMap < ContractAddress , PreimageMap > >
987+ where
988+ StorageLayout : NodeLayoutFor < StarknetStorageValue > + Send + ' static ,
989+ <StorageLayout as NodeLayoutFor < StarknetStorageValue > >:: DbLeaf :
990+ HasStaticPrefix < KeyContext = ContractAddress > ,
991+ ContractLeaf : AsRef < ContractState > ,
992+ {
993+ let mut contracts_trie_storage_proofs =
994+ HashMap :: with_capacity ( contract_storage_sorted_leaf_indices. len ( ) ) ;
995+
996+ for ( idx, sorted_leaf_indices) in contract_storage_sorted_leaf_indices {
997+ let Some ( ( contract_address, storage_root_hash) ) =
998+ get_address_and_storage_root ( idx, contract_leaves)
999+ else {
1000+ continue ;
1001+ } ;
1002+
1003+ let leaves = None ;
1004+ let proof = fetch_patricia_paths :: < StorageLayout :: DbLeaf , StorageLayout > (
1005+ storage,
1006+ storage_root_hash,
1007+ * sorted_leaf_indices,
1008+ leaves,
1009+ & contract_address,
1010+ )
1011+ . await ?;
1012+ contracts_trie_storage_proofs. insert ( contract_address, proof) ;
1013+ }
1014+
1015+ Ok ( contracts_trie_storage_proofs)
1016+ }
1017+
1018+ /// Concurrently fetches Patricia proofs for the storage tries.
1019+ #[ allow( dead_code) ]
1020+ async fn fetch_contract_storage_paths_concurrently < S , StorageLayout , ContractLeaf > (
1021+ storage : & mut S ,
1022+ contract_storage_sorted_leaf_indices : & HashMap < NodeIndex , SortedLeafIndices < ' _ > > ,
1023+ contract_leaves : & HashMap < NodeIndex , ContractLeaf > ,
1024+ ) -> TraversalResult < HashMap < ContractAddress , PreimageMap > >
1025+ where
1026+ S : GatherableStorage ,
1027+ StorageLayout : NodeLayoutFor < StarknetStorageValue > + Send + ' static ,
1028+ <StorageLayout as NodeLayoutFor < StarknetStorageValue > >:: DbLeaf :
1029+ HasStaticPrefix < KeyContext = ContractAddress > ,
1030+ ContractLeaf : AsRef < ContractState > ,
1031+ {
1032+ let mut tasks = Vec :: new ( ) ;
1033+ for ( idx, sorted_leaf_indices) in contract_storage_sorted_leaf_indices {
1034+ let Some ( ( contract_address, storage_root_hash) ) =
1035+ get_address_and_storage_root ( idx, contract_leaves)
1036+ else {
1037+ continue ;
1038+ } ;
1039+ tasks. push ( StoragePathsReadTask :: < StorageLayout > {
1040+ address : contract_address,
1041+ storage_root_hash,
1042+ sorted_leaf_indices : * sorted_leaf_indices,
1043+ _layout : PhantomData ,
1044+ } ) ;
1045+ }
1046+ storage. gather ( tasks) . await . into_iter ( ) . collect ( )
1047+ }
1048+
9281049/// Helper function to create a storage trie for a single contract.
9291050async fn create_storage_trie < ' a , Layout : NodeLayoutFor < StarknetStorageValue > > (
9301051 storage : & mut impl ReadOnlyStorage ,
0 commit comments