@@ -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,128 @@ 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+ ///
965+ /// In either case, the storage trie of this contract is empty, so there is nothing to
966+ /// prove regarding the contract storage.
967+ pub ( crate ) fn get_address_and_storage_root < ContractLeaf : AsRef < ContractState > > (
968+ idx : & NodeIndex ,
969+ contract_leaves : & HashMap < NodeIndex , ContractLeaf > ,
970+ ) -> Option < ( ContractAddress , HashOutput ) > {
971+ let contract_address = try_node_index_into_contract_address ( idx) . unwrap_or_else ( |_| {
972+ panic ! (
973+ "Converting leaf NodeIndex to ContractAddress should succeed; failed to convert \
974+ {idx:?}."
975+ )
976+ } ) ;
977+ let storage_root_hash = contract_leaves. get ( idx) . map ( |leaf| leaf. as_ref ( ) . storage_root_hash ) ?;
978+ Some ( ( contract_address, storage_root_hash) )
979+ }
980+
981+ /// Sequentially fetches Patricia proofs for the storage tries.
982+ #[ allow( dead_code) ]
983+ async fn fetch_contract_storage_paths_sequentially < StorageLayout , ContractLeaf > (
984+ storage : & mut impl ReadOnlyStorage ,
985+ contract_storage_sorted_leaf_indices : & HashMap < NodeIndex , SortedLeafIndices < ' _ > > ,
986+ contract_leaves : & HashMap < NodeIndex , ContractLeaf > ,
987+ ) -> TraversalResult < HashMap < ContractAddress , PreimageMap > >
988+ where
989+ StorageLayout : NodeLayoutFor < StarknetStorageValue > + Send + ' static ,
990+ <StorageLayout as NodeLayoutFor < StarknetStorageValue > >:: DbLeaf :
991+ HasStaticPrefix < KeyContext = ContractAddress > ,
992+ ContractLeaf : AsRef < ContractState > ,
993+ {
994+ let mut contracts_trie_storage_proofs =
995+ HashMap :: with_capacity ( contract_storage_sorted_leaf_indices. len ( ) ) ;
996+
997+ for ( idx, sorted_leaf_indices) in contract_storage_sorted_leaf_indices {
998+ let Some ( ( contract_address, storage_root_hash) ) =
999+ get_address_and_storage_root ( idx, contract_leaves)
1000+ else {
1001+ continue ;
1002+ } ;
1003+
1004+ let leaves = None ;
1005+ let proof = fetch_patricia_paths :: < StorageLayout :: DbLeaf , StorageLayout > (
1006+ storage,
1007+ storage_root_hash,
1008+ * sorted_leaf_indices,
1009+ leaves,
1010+ & contract_address,
1011+ )
1012+ . await ?;
1013+ contracts_trie_storage_proofs. insert ( contract_address, proof) ;
1014+ }
1015+
1016+ Ok ( contracts_trie_storage_proofs)
1017+ }
1018+
1019+ /// Concurrently fetches Patricia proofs for the storage tries.
1020+ #[ allow( dead_code) ]
1021+ async fn fetch_contract_storage_paths_concurrently < S , StorageLayout , ContractLeaf > (
1022+ storage : & mut S ,
1023+ contract_storage_sorted_leaf_indices : & HashMap < NodeIndex , SortedLeafIndices < ' _ > > ,
1024+ contract_leaves : & HashMap < NodeIndex , ContractLeaf > ,
1025+ ) -> TraversalResult < HashMap < ContractAddress , PreimageMap > >
1026+ where
1027+ S : GatherableStorage ,
1028+ StorageLayout : NodeLayoutFor < StarknetStorageValue > + Send + ' static ,
1029+ <StorageLayout as NodeLayoutFor < StarknetStorageValue > >:: DbLeaf :
1030+ HasStaticPrefix < KeyContext = ContractAddress > ,
1031+ ContractLeaf : AsRef < ContractState > ,
1032+ {
1033+ let mut tasks = Vec :: new ( ) ;
1034+ for ( idx, sorted_leaf_indices) in contract_storage_sorted_leaf_indices {
1035+ let Some ( ( contract_address, storage_root_hash) ) =
1036+ get_address_and_storage_root ( idx, contract_leaves)
1037+ else {
1038+ continue ;
1039+ } ;
1040+ tasks. push ( StoragePathsReadTask :: < StorageLayout > {
1041+ address : contract_address,
1042+ storage_root_hash,
1043+ sorted_leaf_indices : * sorted_leaf_indices,
1044+ _layout : PhantomData ,
1045+ } ) ;
1046+ }
1047+ storage. gather ( tasks) . await . into_iter ( ) . collect ( )
1048+ }
1049+
9281050/// Helper function to create a storage trie for a single contract.
9291051async fn create_storage_trie < ' a , Layout : NodeLayoutFor < StarknetStorageValue > > (
9301052 storage : & mut impl ReadOnlyStorage ,
0 commit comments