@@ -3,6 +3,7 @@ use std::collections::HashMap;
33use std:: fmt:: Debug ;
44
55use starknet_api:: hash:: HashOutput ;
6+ use starknet_patricia:: patricia_merkle_tree:: filled_tree:: node:: FilledNode ;
67use starknet_patricia:: patricia_merkle_tree:: node_data:: inner_node:: {
78 BinaryData ,
89 EdgeData ,
@@ -18,13 +19,15 @@ use starknet_patricia::patricia_merkle_tree::original_skeleton_tree::tree::{
1819 OriginalSkeletonTreeImpl ,
1920 OriginalSkeletonTreeResult ,
2021} ;
21- use starknet_patricia:: patricia_merkle_tree:: traversal:: SubTreeTrait ;
22+ use starknet_patricia:: patricia_merkle_tree:: traversal:: { SubTreeTrait , UnmodifiedChildTraversal } ;
2223use starknet_patricia:: patricia_merkle_tree:: types:: { NodeIndex , SortedLeafIndices } ;
23- use starknet_patricia_storage:: db_object:: HasStaticPrefix ;
24+ use starknet_patricia_storage:: db_object:: { DBObject , HasStaticPrefix } ;
2425use starknet_patricia_storage:: storage_trait:: Storage ;
2526use tracing:: warn;
2627
27- use crate :: db:: facts_db:: traversal:: calculate_subtrees_roots;
28+ use crate :: db:: db_layout:: NodeLayout ;
29+ use crate :: db:: facts_db:: db:: FactsNodeLayout ;
30+ use crate :: db:: facts_db:: traversal:: get_roots_from_storage;
2831use crate :: db:: facts_db:: types:: FactsSubTree ;
2932
3033#[ cfg( test) ]
@@ -42,65 +45,85 @@ macro_rules! log_trivial_modification {
4245/// Given a list of subtrees, traverses towards their leaves and fetches all non-empty,
4346/// unmodified nodes. If `compare_modified_leaves` is set, function logs out a warning when
4447/// encountering a trivial modification. Fills the previous leaf values if it is not none.
45- async fn fetch_nodes < ' a , L : Leaf > (
48+ async fn fetch_nodes < ' a , L , Layout > (
4649 skeleton_tree : & mut OriginalSkeletonTreeImpl < ' a > ,
47- subtrees : Vec < FactsSubTree < ' a > > ,
50+ subtrees : Vec < Layout :: SubTree > ,
4851 storage : & mut impl Storage ,
4952 leaf_modifications : & LeafModifications < L > ,
5053 config : & impl OriginalSkeletonTreeConfig < L > ,
5154 mut previous_leaves : Option < & mut HashMap < NodeIndex , L > > ,
5255 key_context : & <L as HasStaticPrefix >:: KeyContext ,
53- ) -> OriginalSkeletonTreeResult < ( ) > {
56+ ) -> OriginalSkeletonTreeResult < ( ) >
57+ where
58+ L : Leaf ,
59+ Layout : NodeLayout < ' a , L > ,
60+ FilledNode < L , Layout :: NodeData > : DBObject < DeserializeContext = Layout :: DeserializationContext > ,
61+ {
5462 let mut current_subtrees = subtrees;
5563 let mut next_subtrees = Vec :: new ( ) ;
5664 while !current_subtrees. is_empty ( ) {
5765 let should_fetch_modified_leaves =
5866 config. compare_modified_leaves ( ) || previous_leaves. is_some ( ) ;
5967 let filled_roots =
60- calculate_subtrees_roots :: < L > ( & current_subtrees, storage, key_context) . await ?;
68+ get_roots_from_storage :: < L , Layout > ( & current_subtrees, storage, key_context) . await ?;
6169 for ( filled_root, subtree) in filled_roots. into_iter ( ) . zip ( current_subtrees. iter ( ) ) {
6270 match filled_root. data {
6371 // Binary node.
6472 NodeData :: Binary ( BinaryData { left_data, right_data } ) => {
6573 if subtree. is_unmodified ( ) {
6674 skeleton_tree. nodes . insert (
67- subtree. root_index ,
75+ subtree. get_root_index ( ) ,
6876 OriginalSkeletonNode :: UnmodifiedSubTree ( filled_root. hash ) ,
6977 ) ;
7078 continue ;
7179 }
72- skeleton_tree. nodes . insert ( subtree. root_index , OriginalSkeletonNode :: Binary ) ;
80+ skeleton_tree
81+ . nodes
82+ . insert ( subtree. get_root_index ( ) , OriginalSkeletonNode :: Binary ) ;
7383 let ( left_subtree, right_subtree) =
7484 subtree. get_children_subtrees ( left_data, right_data) ;
7585
7686 handle_subtree (
7787 skeleton_tree,
7888 & mut next_subtrees,
7989 left_subtree,
90+ left_data,
8091 should_fetch_modified_leaves,
8192 ) ;
8293 handle_subtree (
8394 skeleton_tree,
8495 & mut next_subtrees,
8596 right_subtree,
97+ right_data,
8698 should_fetch_modified_leaves,
8799 )
88100 }
89101 // Edge node.
90102 NodeData :: Edge ( EdgeData { bottom_data, path_to_bottom } ) => {
91- skeleton_tree
92- . nodes
93- . insert ( subtree. root_index , OriginalSkeletonNode :: Edge ( path_to_bottom) ) ;
94- if subtree. is_unmodified ( ) {
95- skeleton_tree. nodes . insert (
96- path_to_bottom. bottom_index ( subtree. root_index ) ,
97- OriginalSkeletonNode :: UnmodifiedSubTree ( bottom_data) ,
98- ) ;
99- continue ;
100- }
103+ skeleton_tree. nodes . insert (
104+ subtree. get_root_index ( ) ,
105+ OriginalSkeletonNode :: Edge ( path_to_bottom) ,
106+ ) ;
107+
101108 // Parse bottom.
102109 let ( bottom_subtree, previously_empty_leaves_indices) =
103110 subtree. get_bottom_subtree ( & path_to_bottom, bottom_data) ;
111+
112+ if subtree. is_unmodified ( ) {
113+ match Layout :: SubTree :: should_traverse_unmodified_child ( bottom_data) {
114+ UnmodifiedChildTraversal :: Traverse => {
115+ next_subtrees. push ( bottom_subtree) ;
116+ }
117+ UnmodifiedChildTraversal :: Skip ( unmodified_child_hash) => {
118+ skeleton_tree. nodes . insert (
119+ path_to_bottom. bottom_index ( subtree. get_root_index ( ) ) ,
120+ OriginalSkeletonNode :: UnmodifiedSubTree ( unmodified_child_hash) ,
121+ ) ;
122+ }
123+ }
124+ continue ;
125+ }
126+
104127 if let Some ( ref mut leaves) = previous_leaves {
105128 leaves. extend (
106129 previously_empty_leaves_indices
@@ -119,23 +142,28 @@ async fn fetch_nodes<'a, L: Leaf>(
119142 skeleton_tree,
120143 & mut next_subtrees,
121144 bottom_subtree,
145+ bottom_data,
122146 should_fetch_modified_leaves,
123147 ) ;
124148 }
125149 // Leaf node.
126150 NodeData :: Leaf ( previous_leaf) => {
127151 if subtree. is_unmodified ( ) {
128- warn ! ( "Unexpectedly deserialized leaf sibling." )
152+ skeleton_tree. nodes . insert (
153+ subtree. get_root_index ( ) ,
154+ OriginalSkeletonNode :: UnmodifiedSubTree ( filled_root. hash ) ,
155+ ) ;
129156 } else {
157+ let root_index = subtree. get_root_index ( ) ;
130158 // Modified leaf.
131159 if config. compare_modified_leaves ( )
132- && L :: compare ( leaf_modifications, & subtree . root_index , & previous_leaf) ?
160+ && L :: compare ( leaf_modifications, & root_index, & previous_leaf) ?
133161 {
134- log_trivial_modification ! ( subtree . root_index, previous_leaf) ;
162+ log_trivial_modification ! ( root_index, previous_leaf) ;
135163 }
136164 // If previous values of modified leaves are requested, add this leaf.
137165 if let Some ( ref mut leaves) = previous_leaves {
138- leaves. insert ( subtree . root_index , previous_leaf) ;
166+ leaves. insert ( root_index, previous_leaf) ;
139167 }
140168 }
141169 }
@@ -168,7 +196,7 @@ pub async fn create_original_skeleton_tree<'a, L: Leaf>(
168196 }
169197 let main_subtree = FactsSubTree :: create ( sorted_leaf_indices, NodeIndex :: ROOT , root_hash) ;
170198 let mut skeleton_tree = OriginalSkeletonTreeImpl { nodes : HashMap :: new ( ) , sorted_leaf_indices } ;
171- fetch_nodes :: < L > (
199+ fetch_nodes :: < L , FactsNodeLayout > (
172200 & mut skeleton_tree,
173201 vec ! [ main_subtree] ,
174202 storage,
@@ -202,7 +230,7 @@ pub async fn create_original_skeleton_tree_and_get_previous_leaves<'a, L: Leaf>(
202230 let main_subtree = FactsSubTree :: create ( sorted_leaf_indices, NodeIndex :: ROOT , root_hash) ;
203231 let mut skeleton_tree = OriginalSkeletonTreeImpl { nodes : HashMap :: new ( ) , sorted_leaf_indices } ;
204232 let mut leaves = HashMap :: new ( ) ;
205- fetch_nodes :: < L > (
233+ fetch_nodes :: < L , FactsNodeLayout > (
206234 & mut skeleton_tree,
207235 vec ! [ main_subtree] ,
208236 storage,
@@ -240,19 +268,41 @@ pub async fn get_leaves<'a, L: Leaf>(
240268
241269/// Handles a subtree referred by an edge or a binary node. Decides whether we deserialize the
242270/// referred subtree or not.
243- fn handle_subtree < ' a > (
271+ fn handle_subtree < ' a , SubTree : SubTreeTrait < ' a > > (
244272 skeleton_tree : & mut OriginalSkeletonTreeImpl < ' a > ,
245- next_subtrees : & mut Vec < FactsSubTree < ' a > > ,
246- subtree : FactsSubTree < ' a > ,
273+ next_subtrees : & mut Vec < SubTree > ,
274+ subtree : SubTree ,
275+ subtree_data : SubTree :: NodeData ,
247276 should_fetch_modified_leaves : bool ,
248277) {
249- if !subtree. is_leaf ( ) || ( should_fetch_modified_leaves && !subtree. is_unmodified ( ) ) {
278+ let is_leaf = subtree. is_leaf ( ) ;
279+ let is_modified = !subtree. is_unmodified ( ) ;
280+
281+ // Internal node → always traverse.
282+ if !is_leaf {
250283 next_subtrees. push ( subtree) ;
251- } else if subtree. is_unmodified ( ) {
252- // Leaf sibling.
253- skeleton_tree
254- . nodes
255- . insert ( subtree. root_index , OriginalSkeletonNode :: UnmodifiedSubTree ( subtree. root_hash ) ) ;
284+ return ;
285+ }
286+
287+ // Modified leaf.
288+ if is_modified {
289+ if should_fetch_modified_leaves {
290+ next_subtrees. push ( subtree) ;
291+ }
292+ return ;
293+ }
294+
295+ // Unmodified leaf sibling.
296+ match SubTree :: should_traverse_unmodified_child ( subtree_data) {
297+ UnmodifiedChildTraversal :: Traverse => {
298+ next_subtrees. push ( subtree) ;
299+ }
300+ UnmodifiedChildTraversal :: Skip ( unmodified_child_hash) => {
301+ skeleton_tree. nodes . insert (
302+ subtree. get_root_index ( ) ,
303+ OriginalSkeletonNode :: UnmodifiedSubTree ( unmodified_child_hash) ,
304+ ) ;
305+ }
256306 }
257307}
258308
0 commit comments