@@ -4,7 +4,8 @@ use starknet_api::core::{ClassHash, ContractAddress};
44use starknet_api:: hash:: HashOutput ;
55use starknet_patricia:: patricia_merkle_tree:: original_skeleton_tree:: config:: OriginalSkeletonTreeConfig ;
66use starknet_patricia:: patricia_merkle_tree:: traversal:: TraversalResult ;
7- use starknet_patricia:: patricia_merkle_tree:: types:: { NodeIndex , SortedLeafIndices } ;
7+ use starknet_patricia:: patricia_merkle_tree:: types:: NodeIndex ;
8+ pub use starknet_patricia:: patricia_merkle_tree:: types:: SortedLeafIndices ;
89use starknet_patricia_storage:: db_object:: EmptyKeyContext ;
910use starknet_patricia_storage:: storage_trait:: ReadOnlyStorage ;
1011
@@ -50,6 +51,57 @@ impl OriginalSkeletonTreeConfig for OriginalSkeletonTrieConfig {
5051 }
5152}
5253
54+ /// Requested trie leaves for Patricia witness collection (classes trie, contracts trie, and
55+ /// per-contract storage leaves). Built via [`LeavesRequest::from`].
56+ #[ derive( Clone ) ]
57+ pub struct LeavesRequest {
58+ pub class_leaf_indices : Vec < NodeIndex > ,
59+ pub contract_leaf_indices : Vec < NodeIndex > ,
60+ pub contract_storage_leaf_indices : HashMap < NodeIndex , Vec < NodeIndex > > ,
61+ }
62+
63+ impl LeavesRequest {
64+ /// Builds index buffers expected by [`fetch_all_patricia_paths`].
65+ pub fn from (
66+ class_hashes : & [ ClassHash ] ,
67+ contract_addresses : & [ ContractAddress ] ,
68+ contract_storage_keys : & HashMap < ContractAddress , Vec < StarknetStorageKey > > ,
69+ ) -> Self {
70+ let contract_leaf_indices: Vec < NodeIndex > =
71+ contract_addresses. iter ( ) . map ( contract_address_into_node_index) . collect ( ) ;
72+ let contract_storage_leaf_indices: HashMap < NodeIndex , Vec < NodeIndex > > =
73+ contract_storage_keys
74+ . iter ( )
75+ . map ( |( address, keys) | {
76+ let node_index = contract_address_into_node_index ( address) ;
77+ let leaf_indices: Vec < _ > = keys. iter ( ) . map ( NodeIndex :: from) . collect ( ) ;
78+ ( node_index, leaf_indices)
79+ } )
80+ . collect ( ) ;
81+ Self {
82+ class_leaf_indices : class_hashes. iter ( ) . map ( class_hash_into_node_index) . collect ( ) ,
83+ contract_leaf_indices,
84+ contract_storage_leaf_indices,
85+ }
86+ }
87+
88+ /// Sorts class, contract, and per-contract storage leaf index buffers in place, then returns
89+ /// [`SortedLeafIndices`] views.
90+ pub fn get_sorted (
91+ & mut self ,
92+ ) -> ( SortedLeafIndices < ' _ > , SortedLeafIndices < ' _ > , HashMap < NodeIndex , SortedLeafIndices < ' _ > > )
93+ {
94+ let class_sorted = SortedLeafIndices :: new ( & mut self . class_leaf_indices ) ;
95+ let contract_sorted = SortedLeafIndices :: new ( & mut self . contract_leaf_indices ) ;
96+ let storage_sorted: HashMap < _ , _ > = self
97+ . contract_storage_leaf_indices
98+ . iter_mut ( )
99+ . map ( |( address, leaf_indices) | ( * address, SortedLeafIndices :: new ( leaf_indices) ) )
100+ . collect ( ) ;
101+ ( class_sorted, contract_sorted, storage_sorted)
102+ }
103+ }
104+
53105/// Fetch all tries patricia paths given the modified leaves.
54106/// Fetch the leaves in the contracts trie only, to be able to get the storage root hashes.
55107/// Assumption: `contract_sorted_leaf_indices` contains all `contract_storage_sorted_leaf_indices`
@@ -179,43 +231,27 @@ pub async fn fetch_previous_and_new_patricia_paths(
179231 contract_addresses : & [ ContractAddress ] ,
180232 contract_storage_keys : & HashMap < ContractAddress , Vec < StarknetStorageKey > > ,
181233) -> TraversalResult < StarknetForestProofs > {
182- let mut class_leaf_indices: Vec < NodeIndex > =
183- class_hashes. iter ( ) . map ( class_hash_into_node_index) . collect ( ) ;
184- let class_sorted_leaf_indices = SortedLeafIndices :: new ( & mut class_leaf_indices) ;
185-
186- let mut contract_leaf_indices: Vec < NodeIndex > =
187- contract_addresses. iter ( ) . map ( contract_address_into_node_index) . collect ( ) ;
188- let contract_sorted_leaf_indices = SortedLeafIndices :: new ( & mut contract_leaf_indices) ;
189-
190- let mut contract_storage_leaf_indices: HashMap < NodeIndex , Vec < NodeIndex > > =
191- contract_storage_keys
192- . iter ( )
193- . map ( |( address, keys) | {
194- let node_index = contract_address_into_node_index ( address) ;
195- let leaf_indices: Vec < _ > = keys. iter ( ) . map ( NodeIndex :: from) . collect ( ) ;
196- ( node_index, leaf_indices)
197- } )
198- . collect ( ) ;
199- let contract_storage_sorted_leaf_indices = & contract_storage_leaf_indices
200- . iter_mut ( )
201- . map ( |( address, leaf_indices) | ( * address, SortedLeafIndices :: new ( leaf_indices) ) )
202- . collect ( ) ;
234+ let mut leaves_request =
235+ LeavesRequest :: from ( class_hashes, contract_addresses, contract_storage_keys) ;
236+
237+ let ( class_sorted, contract_sorted, storage_sorted) = leaves_request. get_sorted ( ) ;
203238 let prev_proofs = fetch_all_patricia_paths :: < FactsNodeLayout > (
204239 storage,
205240 classes_trie_root_hashes. previous_root_hash ,
206241 contracts_trie_root_hashes. previous_root_hash ,
207- class_sorted_leaf_indices ,
208- contract_sorted_leaf_indices ,
209- contract_storage_sorted_leaf_indices ,
242+ class_sorted ,
243+ contract_sorted ,
244+ & storage_sorted ,
210245 )
211246 . await ?;
247+
212248 let new_proofs = fetch_all_patricia_paths :: < FactsNodeLayout > (
213249 storage,
214250 classes_trie_root_hashes. new_root_hash ,
215251 contracts_trie_root_hashes. new_root_hash ,
216- class_sorted_leaf_indices ,
217- contract_sorted_leaf_indices ,
218- contract_storage_sorted_leaf_indices ,
252+ class_sorted ,
253+ contract_sorted ,
254+ & storage_sorted ,
219255 )
220256 . await ?;
221257
0 commit comments