1- use starknet_api:: hash:: HashOutput ;
21use starknet_patricia_storage:: errors:: { DeserializationError , StorageError } ;
3- use starknet_patricia_storage:: storage_trait:: PatriciaStorageError ;
2+ use starknet_patricia_storage:: storage_trait:: { DbKeyPrefix , PatriciaStorageError } ;
43use thiserror:: Error ;
54
6- use crate :: patricia_merkle_tree:: filled_tree:: node_serde:: PatriciaPrefix ;
75use crate :: patricia_merkle_tree:: node_data:: inner_node:: PathToBottom ;
86use crate :: patricia_merkle_tree:: node_data:: leaf:: Leaf ;
97use crate :: patricia_merkle_tree:: original_skeleton_tree:: utils:: split_leaves;
@@ -25,88 +23,84 @@ pub enum TraversalError {
2523
2624pub type TraversalResult < T > = Result < T , TraversalError > ;
2725
28- #[ derive( Debug , PartialEq ) ]
29- pub struct SubTree < ' a > {
30- pub sorted_leaf_indices : SortedLeafIndices < ' a > ,
31- pub root_index : NodeIndex ,
32- pub root_hash : HashOutput ,
33- }
26+ /// A trait that allows traversing a trie without knowledge of the concrete node types and data or
27+ /// storage layout.
28+ pub trait SubTreeTrait < ' a > : Sized {
29+ /// Extra data a node can carry about its children (e.g. their hashes).
30+ type NodeData : Copy ;
3431
35- impl < ' a > SubTree < ' a > {
36- pub ( crate ) fn get_height ( & self ) -> SubTreeHeight {
37- SubTreeHeight :: new ( SubTreeHeight :: ACTUAL_HEIGHT . 0 - ( self . root_index . bit_length ( ) - 1 ) )
38- }
32+ /// Creates a concrete child node given its index and data.
33+ fn create (
34+ sorted_leaf_indices : SortedLeafIndices < ' a > ,
35+ root_index : NodeIndex ,
36+ node_data : Self :: NodeData ,
37+ ) -> Self ;
38+
39+ fn get_root_index ( & self ) -> NodeIndex ;
3940
40- pub ( crate ) fn split_leaves ( & self ) -> [ SortedLeafIndices < ' a > ; 2 ] {
41- split_leaves ( & self . root_index , & self . sorted_leaf_indices )
41+ fn get_sorted_leaf_indices ( & self ) -> & SortedLeafIndices < ' a > ;
42+
43+ fn get_height ( & self ) -> SubTreeHeight {
44+ SubTreeHeight :: new (
45+ SubTreeHeight :: ACTUAL_HEIGHT . 0 - ( self . get_root_index ( ) . bit_length ( ) - 1 ) ,
46+ )
4247 }
4348
44- pub fn is_unmodified ( & self ) -> bool {
45- self . sorted_leaf_indices . is_empty ( )
49+ fn split_leaves ( & self ) -> [ SortedLeafIndices < ' a > ; 2 ] {
50+ split_leaves ( & self . get_root_index ( ) , self . get_sorted_leaf_indices ( ) )
4651 }
4752
48- pub fn get_root_prefix < L : Leaf > ( & self ) -> PatriciaPrefix {
49- if self . is_leaf ( ) {
50- PatriciaPrefix :: Leaf ( L :: get_static_prefix ( ) )
51- } else {
52- PatriciaPrefix :: InnerNode
53- }
53+ fn is_unmodified ( & self ) -> bool {
54+ self . get_sorted_leaf_indices ( ) . is_empty ( )
5455 }
5556
5657 /// Returns the bottom subtree which is referred from `self` by the given path. When creating
5758 /// the bottom subtree some indices that were modified under `self` are not modified under the
5859 /// bottom subtree (leaves that were previously empty). These indices are returned as well.
59- pub fn get_bottom_subtree (
60+ fn get_bottom_subtree (
6061 & self ,
6162 path_to_bottom : & PathToBottom ,
62- bottom_hash : HashOutput ,
63- ) -> ( Self , Vec < & NodeIndex > ) {
64- let bottom_index = path_to_bottom. bottom_index ( self . root_index ) ;
63+ bottom_data : Self :: NodeData ,
64+ ) -> ( Self , Vec < NodeIndex > ) {
65+ let sorted_leaf_indices = self . get_sorted_leaf_indices ( ) ;
66+ let bottom_index = path_to_bottom. bottom_index ( self . get_root_index ( ) ) ;
6567 let bottom_height = self . get_height ( ) - SubTreeHeight :: new ( path_to_bottom. length . into ( ) ) ;
6668 let leftmost_in_subtree = bottom_index << bottom_height. into ( ) ;
6769 let rightmost_in_subtree =
6870 leftmost_in_subtree - NodeIndex :: ROOT + ( NodeIndex :: ROOT << bottom_height. into ( ) ) ;
69- let leftmost_index = self . sorted_leaf_indices . bisect_left ( & leftmost_in_subtree) ;
70- let rightmost_index = self . sorted_leaf_indices . bisect_right ( & rightmost_in_subtree) ;
71- let bottom_leaves = self . sorted_leaf_indices . subslice ( leftmost_index, rightmost_index) ;
72- let previously_empty_leaf_indices = self . sorted_leaf_indices . get_indices ( )
73- [ ..leftmost_index]
71+ let leftmost_index = sorted_leaf_indices. bisect_left ( & leftmost_in_subtree) ;
72+ let rightmost_index = sorted_leaf_indices. bisect_right ( & rightmost_in_subtree) ;
73+ let bottom_leaves = sorted_leaf_indices. subslice ( leftmost_index, rightmost_index) ;
74+ let previously_empty_leaf_indices = sorted_leaf_indices. get_indices ( ) [ ..leftmost_index]
7475 . iter ( )
75- . chain ( self . sorted_leaf_indices . get_indices ( ) [ rightmost_index..] . iter ( ) )
76+ . chain ( sorted_leaf_indices. get_indices ( ) [ rightmost_index..] . iter ( ) )
77+ . cloned ( )
7678 . collect ( ) ;
7779
78- (
79- Self {
80- sorted_leaf_indices : bottom_leaves,
81- root_index : bottom_index,
82- root_hash : bottom_hash,
83- } ,
84- previously_empty_leaf_indices,
85- )
80+ ( Self :: create ( bottom_leaves, bottom_index, bottom_data) , previously_empty_leaf_indices)
8681 }
8782
88- pub fn get_children_subtrees (
83+ fn get_children_subtrees (
8984 & self ,
90- left_hash : HashOutput ,
91- right_hash : HashOutput ,
85+ left_data : Self :: NodeData ,
86+ right_data : Self :: NodeData ,
9287 ) -> ( Self , Self ) {
9388 let [ left_leaves, right_leaves] = self . split_leaves ( ) ;
94- let left_root_index = self . root_index * 2 . into ( ) ;
89+ let left_root_index = self . get_root_index ( ) * 2 . into ( ) ;
9590 (
96- SubTree {
97- sorted_leaf_indices : left_leaves,
98- root_index : left_root_index,
99- root_hash : left_hash,
100- } ,
101- SubTree {
102- sorted_leaf_indices : right_leaves,
103- root_index : left_root_index + NodeIndex :: ROOT ,
104- root_hash : right_hash,
105- } ,
91+ Self :: create ( left_leaves, left_root_index, left_data) ,
92+ Self :: create ( right_leaves, left_root_index + NodeIndex :: ROOT , right_data) ,
10693 )
10794 }
10895
109- pub fn is_leaf ( & self ) -> bool {
110- self . root_index . is_leaf ( )
96+ fn is_leaf ( & self ) -> bool {
97+ self . get_root_index ( ) . is_leaf ( )
11198 }
99+
100+ /// Indicates whether unmodified children should be traversed during the construction of the
101+ /// original skeleton tree.
102+ fn should_traverse_unmodified_children ( ) -> bool ;
103+
104+ /// Returns the [DbKeyPrefix] of the root node.
105+ fn get_root_prefix < L : Leaf > ( & self ) -> DbKeyPrefix ;
112106}
0 commit comments