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,86 @@ 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+ // The SubTreeTrait allows traversing a trie without knowledge of the concrete node types and data.
27+ pub trait SubTreeTrait < ' a > : Sized {
28+ // A node can carry data about its children (e.g. their hashes).
29+ type ChildData : Copy ;
3430
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- }
31+ // Creates a concrete child node given its index and data.
32+ fn create_child (
33+ sorted_leaf_indices : SortedLeafIndices < ' a > ,
34+ root_index : NodeIndex ,
35+ child_data : Self :: ChildData ,
36+ ) -> Self ;
37+
38+ fn get_root_index ( & self ) -> NodeIndex ;
39+
40+ fn get_sorted_leaf_indices ( & self ) -> & SortedLeafIndices < ' a > ;
3941
40- pub ( crate ) fn split_leaves ( & self ) -> [ SortedLeafIndices < ' a > ; 2 ] {
41- split_leaves ( & self . root_index , & self . sorted_leaf_indices )
42+ fn get_height ( & self ) -> SubTreeHeight {
43+ SubTreeHeight :: new (
44+ SubTreeHeight :: ACTUAL_HEIGHT . 0 - ( self . get_root_index ( ) . bit_length ( ) - 1 ) ,
45+ )
4246 }
4347
44- pub fn is_unmodified ( & self ) -> bool {
45- self . sorted_leaf_indices . is_empty ( )
48+ fn split_leaves ( & self ) -> [ SortedLeafIndices < ' a > ; 2 ] {
49+ split_leaves ( & self . get_root_index ( ) , self . get_sorted_leaf_indices ( ) )
4650 }
4751
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- }
52+ fn is_unmodified ( & self ) -> bool {
53+ self . get_sorted_leaf_indices ( ) . is_empty ( )
5454 }
5555
5656 /// Returns the bottom subtree which is referred from `self` by the given path. When creating
5757 /// the bottom subtree some indices that were modified under `self` are not modified under the
5858 /// bottom subtree (leaves that were previously empty). These indices are returned as well.
59- pub fn get_bottom_subtree (
59+ fn get_bottom_subtree (
6060 & self ,
6161 path_to_bottom : & PathToBottom ,
62- bottom_hash : HashOutput ,
63- ) -> ( Self , Vec < & NodeIndex > ) {
64- let bottom_index = path_to_bottom. bottom_index ( self . root_index ) ;
62+ bottom_data : Self :: ChildData ,
63+ ) -> ( Self , Vec < NodeIndex > ) {
64+ let sorted_leaf_indices = self . get_sorted_leaf_indices ( ) ;
65+ let bottom_index = path_to_bottom. bottom_index ( self . get_root_index ( ) ) ;
6566 let bottom_height = self . get_height ( ) - SubTreeHeight :: new ( path_to_bottom. length . into ( ) ) ;
6667 let leftmost_in_subtree = bottom_index << bottom_height. into ( ) ;
6768 let rightmost_in_subtree =
6869 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]
70+ let leftmost_index = sorted_leaf_indices. bisect_left ( & leftmost_in_subtree) ;
71+ let rightmost_index = sorted_leaf_indices. bisect_right ( & rightmost_in_subtree) ;
72+ let bottom_leaves = sorted_leaf_indices. subslice ( leftmost_index, rightmost_index) ;
73+ let previously_empty_leaf_indices = sorted_leaf_indices. get_indices ( ) [ ..leftmost_index]
7474 . iter ( )
75- . chain ( self . sorted_leaf_indices . get_indices ( ) [ rightmost_index..] . iter ( ) )
75+ . chain ( sorted_leaf_indices. get_indices ( ) [ rightmost_index..] . iter ( ) )
76+ . cloned ( )
7677 . collect ( ) ;
7778
7879 (
79- Self {
80- sorted_leaf_indices : bottom_leaves,
81- root_index : bottom_index,
82- root_hash : bottom_hash,
83- } ,
80+ Self :: create_child ( bottom_leaves, bottom_index, bottom_data) ,
8481 previously_empty_leaf_indices,
8582 )
8683 }
8784
88- pub fn get_children_subtrees (
85+ fn get_children_subtrees (
8986 & self ,
90- left_hash : HashOutput ,
91- right_hash : HashOutput ,
87+ left_data : Self :: ChildData ,
88+ right_data : Self :: ChildData ,
9289 ) -> ( Self , Self ) {
9390 let [ left_leaves, right_leaves] = self . split_leaves ( ) ;
94- let left_root_index = self . root_index * 2 . into ( ) ;
91+ let left_root_index = self . get_root_index ( ) * 2 . into ( ) ;
9592 (
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- } ,
93+ Self :: create_child ( left_leaves, left_root_index, left_data) ,
94+ Self :: create_child ( right_leaves, left_root_index + NodeIndex :: ROOT , right_data) ,
10695 )
10796 }
10897
109- pub fn is_leaf ( & self ) -> bool {
110- self . root_index . is_leaf ( )
98+ fn is_leaf ( & self ) -> bool {
99+ self . get_root_index ( ) . is_leaf ( )
111100 }
101+
102+ // Indicates whether unmodified children should be traversed during the construction of the
103+ // skeleton tree.
104+ fn should_traverse_unmodified_children ( ) -> bool ;
105+
106+ // Returns the db key prefix of the root node.
107+ fn get_root_prefix < L : Leaf > ( & self ) -> DbKeyPrefix ;
112108}
0 commit comments