@@ -24,7 +24,9 @@ use starknet_patricia_storage::db_object::HasStaticPrefix;
2424use starknet_patricia_storage:: storage_trait:: Storage ;
2525use tracing:: warn;
2626
27- use crate :: db:: facts_db:: traversal:: calculate_subtrees_roots;
27+ use crate :: db:: db_layout:: NodeLayout ;
28+ use crate :: db:: facts_db:: db:: FactsNodeLayout ;
29+ use crate :: db:: facts_db:: traversal:: get_roots_from_storage;
2830use crate :: db:: facts_db:: types:: FactsSubTree ;
2931
3032#[ cfg( test) ]
@@ -42,65 +44,95 @@ macro_rules! log_trivial_modification {
4244/// Given a list of subtrees, traverses towards their leaves and fetches all non-empty,
4345/// unmodified nodes. If `compare_modified_leaves` is set, function logs out a warning when
4446/// encountering a trivial modification. Fills the previous leaf values if it is not none.
45- async fn fetch_nodes < ' a , L : Leaf > (
47+ async fn fetch_nodes < ' a , L , Layout , SubTree > (
4648 skeleton_tree : & mut OriginalSkeletonTreeImpl < ' a > ,
47- subtrees : Vec < FactsSubTree < ' a > > ,
49+ subtrees : Vec <
50+ impl SubTreeTrait <
51+ ' a ,
52+ ChildData = Layout :: ChildData ,
53+ NodeContext = Layout :: DeserializationContext ,
54+ > ,
55+ > ,
4856 storage : & mut impl Storage ,
4957 leaf_modifications : & LeafModifications < L > ,
5058 config : & impl OriginalSkeletonTreeConfig < L > ,
5159 mut previous_leaves : Option < & mut HashMap < NodeIndex , L > > ,
5260 key_context : & <L as HasStaticPrefix >:: KeyContext ,
53- ) -> OriginalSkeletonTreeResult < ( ) > {
61+ ) -> OriginalSkeletonTreeResult < ( ) >
62+ where
63+ L : Leaf ,
64+ Layout : NodeLayout < L > ,
65+ SubTree : SubTreeTrait <
66+ ' a ,
67+ ChildData = Layout :: ChildData ,
68+ NodeContext = Layout :: DeserializationContext ,
69+ > ,
70+ {
5471 let mut current_subtrees = subtrees;
5572 let mut next_subtrees = Vec :: new ( ) ;
5673 while !current_subtrees. is_empty ( ) {
5774 let should_fetch_modified_leaves =
5875 config. compare_modified_leaves ( ) || previous_leaves. is_some ( ) ;
5976 let filled_roots =
60- calculate_subtrees_roots :: < L > ( & current_subtrees, storage, key_context) . await ?;
77+ get_roots_from_storage :: < L , Layout > ( & current_subtrees, storage, key_context) . await ?;
6178 for ( filled_root, subtree) in filled_roots. into_iter ( ) . zip ( current_subtrees. iter ( ) ) {
6279 match filled_root. data {
6380 // Binary node.
64- NodeData :: Binary ( BinaryData { left_hash , right_hash } ) => {
81+ NodeData :: Binary ( BinaryData { left_data , right_data } ) => {
6582 if subtree. is_unmodified ( ) {
6683 skeleton_tree. nodes . insert (
67- subtree. root_index ,
84+ subtree. get_root_index ( ) ,
6885 OriginalSkeletonNode :: UnmodifiedSubTree ( filled_root. hash ) ,
6986 ) ;
7087 continue ;
7188 }
72- skeleton_tree. nodes . insert ( subtree. root_index , OriginalSkeletonNode :: Binary ) ;
89+ skeleton_tree
90+ . nodes
91+ . insert ( subtree. get_root_index ( ) , OriginalSkeletonNode :: Binary ) ;
7392 let ( left_subtree, right_subtree) =
74- subtree. get_children_subtrees ( left_hash , right_hash ) ;
93+ subtree. get_children_subtrees ( left_data , right_data ) ;
7594
7695 handle_subtree (
7796 skeleton_tree,
7897 & mut next_subtrees,
7998 left_subtree,
99+ left_data,
80100 should_fetch_modified_leaves,
81101 ) ;
82102 handle_subtree (
83103 skeleton_tree,
84104 & mut next_subtrees,
85105 right_subtree,
106+ right_data,
86107 should_fetch_modified_leaves,
87108 )
88109 }
89110 // Edge node.
90- NodeData :: Edge ( EdgeData { bottom_hash, path_to_bottom } ) => {
91- skeleton_tree
92- . nodes
93- . insert ( subtree. root_index , OriginalSkeletonNode :: Edge ( path_to_bottom) ) ;
111+ NodeData :: Edge ( EdgeData { bottom_data, path_to_bottom } ) => {
112+ skeleton_tree. nodes . insert (
113+ subtree. get_root_index ( ) ,
114+ OriginalSkeletonNode :: Edge ( path_to_bottom) ,
115+ ) ;
116+
117+ // Parse bottom.
118+ let ( bottom_subtree, previously_empty_leaves_indices) =
119+ subtree. get_bottom_subtree ( & path_to_bottom, bottom_data) ;
120+
94121 if subtree. is_unmodified ( ) {
95- skeleton_tree. nodes . insert (
96- path_to_bottom. bottom_index ( subtree. root_index ) ,
97- OriginalSkeletonNode :: UnmodifiedSubTree ( bottom_hash) ,
98- ) ;
122+ if !SubTree :: should_traverse_unmodified_children ( ) {
123+ skeleton_tree. nodes . insert (
124+ path_to_bottom. bottom_index ( subtree. get_root_index ( ) ) ,
125+ OriginalSkeletonNode :: UnmodifiedSubTree (
126+ SubTree :: unmodified_child_hash ( bottom_data) . unwrap ( ) ,
127+ ) ,
128+ ) ;
129+ } else {
130+ // With index layout we need to traverse an unmodified bottom node.
131+ next_subtrees. push ( bottom_subtree)
132+ }
99133 continue ;
100134 }
101- // Parse bottom.
102- let ( bottom_subtree, previously_empty_leaves_indices) =
103- subtree. get_bottom_subtree ( & path_to_bottom, bottom_hash) ;
135+
104136 if let Some ( ref mut leaves) = previous_leaves {
105137 leaves. extend (
106138 previously_empty_leaves_indices
@@ -119,23 +151,28 @@ async fn fetch_nodes<'a, L: Leaf>(
119151 skeleton_tree,
120152 & mut next_subtrees,
121153 bottom_subtree,
154+ bottom_data,
122155 should_fetch_modified_leaves,
123156 ) ;
124157 }
125158 // Leaf node.
126159 NodeData :: Leaf ( previous_leaf) => {
127160 if subtree. is_unmodified ( ) {
128- warn ! ( "Unexpectedly deserialized leaf sibling." )
161+ skeleton_tree. nodes . insert (
162+ subtree. get_root_index ( ) ,
163+ OriginalSkeletonNode :: UnmodifiedSubTree ( filled_root. hash ) ,
164+ ) ;
129165 } else {
166+ let root_index = subtree. get_root_index ( ) ;
130167 // Modified leaf.
131168 if config. compare_modified_leaves ( )
132- && L :: compare ( leaf_modifications, & subtree . root_index , & previous_leaf) ?
169+ && L :: compare ( leaf_modifications, & root_index, & previous_leaf) ?
133170 {
134- log_trivial_modification ! ( subtree . root_index, previous_leaf) ;
171+ log_trivial_modification ! ( root_index, previous_leaf) ;
135172 }
136173 // If previous values of modified leaves are requested, add this leaf.
137174 if let Some ( ref mut leaves) = previous_leaves {
138- leaves. insert ( subtree . root_index , previous_leaf) ;
175+ leaves. insert ( root_index, previous_leaf) ;
139176 }
140177 }
141178 }
@@ -168,7 +205,7 @@ pub async fn create_original_skeleton_tree<'a, L: Leaf>(
168205 }
169206 let main_subtree = FactsSubTree { sorted_leaf_indices, root_index : NodeIndex :: ROOT , root_hash } ;
170207 let mut skeleton_tree = OriginalSkeletonTreeImpl { nodes : HashMap :: new ( ) , sorted_leaf_indices } ;
171- fetch_nodes :: < L > (
208+ fetch_nodes :: < L , FactsNodeLayout , FactsSubTree < ' a > > (
172209 & mut skeleton_tree,
173210 vec ! [ main_subtree] ,
174211 storage,
@@ -202,7 +239,7 @@ pub async fn create_original_skeleton_tree_and_get_previous_leaves<'a, L: Leaf>(
202239 let main_subtree = FactsSubTree { sorted_leaf_indices, root_index : NodeIndex :: ROOT , root_hash } ;
203240 let mut skeleton_tree = OriginalSkeletonTreeImpl { nodes : HashMap :: new ( ) , sorted_leaf_indices } ;
204241 let mut leaves = HashMap :: new ( ) ;
205- fetch_nodes :: < L > (
242+ fetch_nodes :: < L , FactsNodeLayout , FactsSubTree < ' a > > (
206243 & mut skeleton_tree,
207244 vec ! [ main_subtree] ,
208245 storage,
@@ -237,19 +274,40 @@ pub async fn get_leaves<'a, L: Leaf>(
237274
238275/// Handles a subtree referred by an edge or a binary node. Decides whether we deserialize the
239276/// referred subtree or not.
240- fn handle_subtree < ' a > (
277+ fn handle_subtree < ' a , SubTree : SubTreeTrait < ' a > > (
241278 skeleton_tree : & mut OriginalSkeletonTreeImpl < ' a > ,
242- next_subtrees : & mut Vec < FactsSubTree < ' a > > ,
243- subtree : FactsSubTree < ' a > ,
279+ next_subtrees : & mut Vec < SubTree > ,
280+ subtree : SubTree ,
281+ subtree_data : SubTree :: ChildData ,
244282 should_fetch_modified_leaves : bool ,
245283) {
246- if !subtree. is_leaf ( ) || ( should_fetch_modified_leaves && !subtree. is_unmodified ( ) ) {
284+ let is_leaf = subtree. is_leaf ( ) ;
285+ let is_unmodified = subtree. is_unmodified ( ) ;
286+
287+ // 1. Internal node → always traverse.
288+ if !is_leaf {
289+ next_subtrees. push ( subtree) ;
290+ return ;
291+ }
292+
293+ // 2. Modified leaf.
294+ if !is_unmodified {
295+ if should_fetch_modified_leaves {
296+ next_subtrees. push ( subtree) ;
297+ }
298+ return ;
299+ }
300+
301+ // 3. Unmodified leaf sibling.
302+ if !SubTree :: should_traverse_unmodified_children ( ) {
303+ skeleton_tree. nodes . insert (
304+ subtree. get_root_index ( ) ,
305+ OriginalSkeletonNode :: UnmodifiedSubTree (
306+ SubTree :: unmodified_child_hash ( subtree_data) . unwrap ( ) ,
307+ ) ,
308+ ) ;
309+ } else {
247310 next_subtrees. push ( subtree) ;
248- } else if subtree. is_unmodified ( ) {
249- // Leaf sibling.
250- skeleton_tree
251- . nodes
252- . insert ( subtree. root_index , OriginalSkeletonNode :: UnmodifiedSubTree ( subtree. root_hash ) ) ;
253311 }
254312}
255313
0 commit comments