@@ -2,8 +2,10 @@ use std::collections::HashMap;
22
33use pretty_assertions:: assert_eq;
44use rstest:: rstest;
5+ use rstest_reuse:: { apply, template} ;
56use starknet_api:: core:: { ClassHash , ContractAddress , Nonce } ;
67use starknet_api:: hash:: { HashOutput , StateRoots } ;
8+ use starknet_patricia:: db_layout:: TrieType ;
79use starknet_patricia:: patricia_merkle_tree:: external_test_utils:: {
810 create_32_bytes_entry,
911 create_binary_entry_from_u128,
@@ -21,11 +23,14 @@ use starknet_patricia_storage::db_object::{DBObject, EmptyKeyContext};
2123use starknet_patricia_storage:: map_storage:: MapStorage ;
2224use starknet_patricia_storage:: storage_trait:: { DbHashMap , DbKey , DbValue } ;
2325use starknet_types_core:: felt:: Felt ;
26+ use starknet_types_core:: hash:: StarkHash ;
2427
2528use crate :: block_committer:: commit:: get_all_modified_indices;
2629use crate :: block_committer:: input:: {
2730 contract_address_into_node_index,
31+ try_node_index_into_contract_address,
2832 Input ,
33+ InputContext ,
2934 ReaderConfig ,
3035 StarknetStorageKey ,
3136 StarknetStorageValue ,
@@ -34,6 +39,13 @@ use crate::block_committer::input::{
3439use crate :: db:: facts_db:: db:: FactsDb ;
3540use crate :: db:: facts_db:: types:: FactsDbInitialRead ;
3641use crate :: db:: forest_trait:: ForestReader ;
42+ use crate :: db:: index_db:: create_index_tree_test:: convert_facts_db_to_index_db;
43+ use crate :: db:: index_db:: db:: IndexDb ;
44+ use crate :: db:: index_db:: leaves:: {
45+ IndexLayoutCompiledClassHash ,
46+ IndexLayoutContractState ,
47+ IndexLayoutStarknetStorageValue ,
48+ } ;
3749use crate :: forest:: original_skeleton_forest:: { ForestSortedIndices , OriginalSkeletonForest } ;
3850use crate :: patricia_merkle_tree:: leaf:: leaf_impl:: ContractState ;
3951use crate :: patricia_merkle_tree:: types:: CompiledClassHash ;
@@ -58,14 +70,24 @@ pub(crate) fn create_compiled_class_leaf_entry(val: u128) -> (DbKey, DbValue) {
5870 ( leaf. get_db_key ( & EmptyKeyContext , & leaf. 0 . to_bytes_be ( ) ) , leaf. serialize ( ) . unwrap ( ) )
5971}
6072
61- pub ( crate ) fn create_contract_state_leaf_entry ( val : u128 ) -> ( DbKey , DbValue ) {
62- let felt = Felt :: from ( val) ;
73+ pub ( crate ) fn create_contract_state_leaf_entry (
74+ nonce : u128 ,
75+ storage_root : u128 ,
76+ class_hash : u128 ,
77+ hash : Option < u128 > ,
78+ ) -> ( DbKey , DbValue ) {
79+ let ( nonce, storage_root, class_hash) =
80+ ( Felt :: from ( nonce) , Felt :: from ( storage_root) , Felt :: from ( class_hash) ) ;
6381 let leaf = ContractState {
64- nonce : Nonce ( felt ) ,
65- storage_root_hash : HashOutput ( felt ) ,
66- class_hash : ClassHash ( felt ) ,
82+ nonce : Nonce ( nonce ) ,
83+ storage_root_hash : HashOutput ( storage_root ) ,
84+ class_hash : ClassHash ( class_hash ) ,
6785 } ;
68- ( leaf. get_db_key ( & EmptyKeyContext , & felt. to_bytes_be ( ) ) , leaf. serialize ( ) . unwrap ( ) )
86+ let mut hash = hash. map ( Felt :: from) ;
87+ if hash. is_none ( ) {
88+ hash = Some ( AdditionHash :: hash_array ( & [ class_hash, storage_root, nonce] ) ) ;
89+ }
90+ ( leaf. get_db_key ( & EmptyKeyContext , & hash. unwrap ( ) . to_bytes_be ( ) ) , leaf. serialize ( ) . unwrap ( ) )
6991}
7092
7193// This test uses addition hash for simplicity (i.e hash(a,b) = a + b).
@@ -130,7 +152,7 @@ pub(crate) fn create_contract_state_leaf_entry(val: u128) -> (DbKey, DbValue) {
130152/// / \ \ \ / \ \ \
131153/// NZ 2 NZ NZ NZ 9 16 15
132154
133- #[ tokio :: test ]
155+ #[ template ]
134156#[ rstest]
135157#[ case(
136158 Input {
@@ -162,9 +184,11 @@ pub(crate) fn create_contract_state_leaf_entry(val: u128) -> (DbKey, DbValue) {
162184 create_edge_entry_from_u128:: <AdditionHash >( 554 , 1 , 1 ) ,
163185 create_binary_entry_from_u128:: <AdditionHash >( 305 , 556 ) ,
164186 // Contracts trie leaves.
165- create_contract_state_leaf_entry( 277 ) ,
166- create_contract_state_leaf_entry( 303 ) ,
167- create_contract_state_leaf_entry( 1 ) ,
187+ // TODO(Ariel): Why both layouts pass when we lie about the hash?
188+ // probably becaues the original skeleton doesn't care about these hashes (there were modifications).
189+ create_contract_state_leaf_entry( 277 , 277 , 277 , Some ( 277 ) ) ,
190+ create_contract_state_leaf_entry( 303 , 303 , 303 , Some ( 303 ) ) ,
191+ create_contract_state_leaf_entry( 0 , 0 , 1 , None ) ,
168192 // Classes trie inner nodes.
169193 create_binary_entry_from_u128:: <AdditionHash >( 33 , 47 ) ,
170194 create_edge_entry_from_u128:: <AdditionHash >( 72 , 1 , 1 ) ,
@@ -295,17 +319,85 @@ pub(crate) fn create_contract_state_leaf_entry(val: u128) -> (DbKey, DbValue) {
295319 vec![ 6 , 7 , 0 ] ,
296320 vec![ 7 , 6 , 0 ] ,
297321) ]
298- async fn test_create_original_skeleton_forest (
322+ fn create_original_skeleton_forest_cases (
323+ #[ case] input : Input < FactsDbInitialRead > ,
324+ #[ case] storage : MapStorage ,
325+ #[ case] expected_forest : OriginalSkeletonForest < ' _ > ,
326+ #[ case] expected_original_contracts_trie_leaves : HashMap < ContractAddress , ContractState > ,
327+ #[ case] expected_storage_tries_sorted_indices : HashMap < u128 , Vec < u128 > > ,
328+ #[ case] expected_contracts_trie_sorted_indices : Vec < u128 > ,
329+ #[ case] expected_classes_trie_sorted_indices : Vec < u128 > ,
330+ ) {
331+ }
332+
333+ #[ apply( create_original_skeleton_forest_cases) ]
334+ #[ rstest]
335+ #[ tokio:: test]
336+ async fn test_create_original_skeleton_forest_facts_layout (
299337 #[ case] input : Input < FactsDbInitialRead > ,
300338 #[ case] storage : MapStorage ,
301339 #[ case] expected_forest : OriginalSkeletonForest < ' _ > ,
302340 #[ case] expected_original_contracts_trie_leaves : HashMap < ContractAddress , ContractState > ,
303341 #[ case] expected_storage_tries_sorted_indices : HashMap < u128 , Vec < u128 > > ,
304342 #[ case] expected_contracts_trie_sorted_indices : Vec < u128 > ,
305343 #[ case] expected_classes_trie_sorted_indices : Vec < u128 > ,
344+ ) {
345+ test_create_original_skeleton_forest :: < FactsDbInitialRead , FactsDb < MapStorage > > (
346+ input,
347+ storage,
348+ expected_forest,
349+ expected_original_contracts_trie_leaves,
350+ expected_storage_tries_sorted_indices,
351+ expected_contracts_trie_sorted_indices,
352+ expected_classes_trie_sorted_indices,
353+ |storage| FactsDb :: new ( storage) ,
354+ )
355+ . await ;
356+ }
357+
358+ #[ apply( create_original_skeleton_forest_cases) ]
359+ #[ rstest]
360+ #[ tokio:: test]
361+ async fn test_create_original_skeleton_forest_index_layout (
362+ #[ case] input : Input < FactsDbInitialRead > ,
363+ #[ case] mut storage : MapStorage ,
364+ #[ case] expected_forest : OriginalSkeletonForest < ' _ > ,
365+ #[ case] expected_original_contracts_trie_leaves : HashMap < ContractAddress , ContractState > ,
366+ #[ case] expected_storage_tries_sorted_indices : HashMap < u128 , Vec < u128 > > ,
367+ #[ case] expected_contracts_trie_sorted_indices : Vec < u128 > ,
368+ #[ case] expected_classes_trie_sorted_indices : Vec < u128 > ,
369+ ) {
370+ let index_storage =
371+ convert_facts_forest_db_to_index_db ( & mut storage, input. initial_read_context . 0 ) . await ;
372+ test_create_original_skeleton_forest :: < FactsDbInitialRead , IndexDb < MapStorage > > (
373+ input,
374+ index_storage,
375+ expected_forest,
376+ expected_original_contracts_trie_leaves,
377+ expected_storage_tries_sorted_indices,
378+ expected_contracts_trie_sorted_indices,
379+ expected_classes_trie_sorted_indices,
380+ |storage| IndexDb :: new ( storage) ,
381+ )
382+ . await ;
383+ }
384+
385+ async fn test_create_original_skeleton_forest <
386+ ReaderInputContext : InputContext ,
387+ Reader : ForestReader < ReaderInputContext > ,
388+ > (
389+ input : Input < ReaderInputContext > ,
390+ storage : MapStorage ,
391+ expected_forest : OriginalSkeletonForest < ' _ > ,
392+ expected_original_contracts_trie_leaves : HashMap < ContractAddress , ContractState > ,
393+ expected_storage_tries_sorted_indices : HashMap < u128 , Vec < u128 > > ,
394+ expected_contracts_trie_sorted_indices : Vec < u128 > ,
395+ expected_classes_trie_sorted_indices : Vec < u128 > ,
396+ reader_generator : impl FnOnce ( MapStorage ) -> Reader ,
306397) {
307398 let ( mut storage_tries_indices, mut contracts_trie_indices, mut classes_trie_indices) =
308399 get_all_modified_indices ( & input. state_diff ) ;
400+
309401 let forest_sorted_indices = ForestSortedIndices {
310402 storage_tries_sorted_indices : storage_tries_indices
311403 . iter_mut ( )
@@ -317,7 +409,8 @@ async fn test_create_original_skeleton_forest(
317409
318410 let actual_storage_updates = input. state_diff . actual_storage_updates ( ) ;
319411 let actual_classes_updates = input. state_diff . actual_classes_updates ( ) ;
320- let ( actual_forest, original_contracts_trie_leaves) = FactsDb :: new ( storage)
412+ let mut reader = reader_generator ( storage) ;
413+ let ( actual_forest, original_contracts_trie_leaves) = reader
321414 . read (
322415 input. initial_read_context ,
323416 & actual_storage_updates,
@@ -355,6 +448,49 @@ async fn test_create_original_skeleton_forest(
355448 }
356449}
357450
451+ async fn convert_facts_forest_db_to_index_db (
452+ storage : & mut MapStorage ,
453+ roots : StateRoots ,
454+ ) -> MapStorage {
455+ let mut contract_leaves: Option < Vec < ( NodeIndex , ContractState ) > > = Some ( Vec :: new ( ) ) ;
456+ let mut index_storage =
457+ convert_facts_db_to_index_db :: < ContractState , IndexLayoutContractState > (
458+ storage,
459+ roots. contracts_trie_root_hash ,
460+ Some ( TrieType :: ContractsTrie ) ,
461+ & mut contract_leaves,
462+ )
463+ . await
464+ . 0 ;
465+
466+ for ( index, contract_leaf) in contract_leaves. unwrap ( ) {
467+ println ! ( "storage tries conversion" ) ;
468+ let contract_address = try_node_index_into_contract_address ( & index) . unwrap ( ) ;
469+ let storage_root = contract_leaf. storage_root_hash ;
470+ let contract_storage_entries =
471+ convert_facts_db_to_index_db :: < StarknetStorageValue , IndexLayoutStarknetStorageValue > (
472+ storage,
473+ storage_root,
474+ Some ( TrieType :: StorageTrie ( contract_address) ) ,
475+ & mut None ,
476+ )
477+ . await ;
478+ index_storage. extend ( contract_storage_entries. 0 ) ;
479+ }
480+
481+ let classes_storage =
482+ convert_facts_db_to_index_db :: < CompiledClassHash , IndexLayoutCompiledClassHash > (
483+ storage,
484+ roots. classes_trie_root_hash ,
485+ Some ( TrieType :: ClassesTrie ) ,
486+ & mut None ,
487+ )
488+ . await ;
489+ index_storage. extend ( classes_storage. 0 ) ;
490+
491+ MapStorage ( index_storage)
492+ }
493+
358494fn create_contract_leaves ( leaves : & [ ( u128 , u128 ) ] ) -> HashMap < ContractAddress , ContractState > {
359495 leaves
360496 . iter ( )
0 commit comments