Skip to content

Commit 27c1f98

Browse files
committed
starknet_committer,starknet_patricia: layout-dependent FilledTree serialization
1 parent fda3843 commit 27c1f98

File tree

7 files changed

+118
-59
lines changed

7 files changed

+118
-59
lines changed

crates/starknet_committer/src/db/external_test_utils.rs

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ use std::collections::HashMap;
22

33
use serde_json::json;
44
use starknet_api::hash::HashOutput;
5+
use starknet_patricia::db_layout::{NodeLayout, TrieType};
56
use starknet_patricia::patricia_merkle_tree::filled_tree::tree::{FilledTree, FilledTreeImpl};
67
use starknet_patricia::patricia_merkle_tree::node_data::leaf::{
8+
Leaf,
79
LeafModifications,
8-
LeafWithEmptyKeyContext,
910
SkeletonLeaf,
1011
};
1112
use starknet_patricia::patricia_merkle_tree::original_skeleton_tree::config::OriginalSkeletonTreeConfig;
@@ -15,33 +16,33 @@ use starknet_patricia::patricia_merkle_tree::updated_skeleton_tree::tree::{
1516
UpdatedSkeletonTree,
1617
UpdatedSkeletonTreeImpl,
1718
};
18-
use starknet_patricia_storage::db_object::EmptyKeyContext;
19+
use starknet_patricia_storage::db_object::HasStaticPrefix;
1920
use starknet_patricia_storage::map_storage::MapStorage;
2021

21-
use crate::db::facts_db::db::FactsNodeLayout;
2222
use crate::db::trie_traversal::create_original_skeleton_tree;
2323

24-
// TODO(Ariel, 14/12/2025): make this generic over the layout.
25-
pub async fn tree_computation_flow<L, TH>(
24+
pub async fn tree_computation_flow<L, Layout, TH>(
2625
leaf_modifications: LeafModifications<L>,
2726
storage: &mut MapStorage,
2827
root_hash: HashOutput,
2928
config: impl OriginalSkeletonTreeConfig,
29+
key_context: &<L as HasStaticPrefix>::KeyContext,
3030
) -> FilledTreeImpl<L>
3131
where
3232
TH: TreeHashFunction<L> + 'static,
33-
L: LeafWithEmptyKeyContext + 'static,
33+
L: Leaf + 'static,
34+
Layout: for<'a> NodeLayout<'a, L> + 'static,
3435
{
3536
let mut sorted_leaf_indices: Vec<NodeIndex> = leaf_modifications.keys().copied().collect();
3637
let sorted_leaf_indices = SortedLeafIndices::new(&mut sorted_leaf_indices);
37-
let mut original_skeleton = create_original_skeleton_tree::<L, FactsNodeLayout>(
38+
let mut original_skeleton = create_original_skeleton_tree::<L, Layout>(
3839
storage,
3940
root_hash,
4041
sorted_leaf_indices,
4142
&config,
4243
&leaf_modifications,
4344
None,
44-
&EmptyKeyContext,
45+
key_context,
4546
)
4647
.await
4748
.expect("Failed to create the original skeleton tree");
@@ -63,28 +64,38 @@ where
6364
)
6465
.expect("Failed to create the updated skeleton tree");
6566

66-
FilledTreeImpl::<L>::create_with_existing_leaves::<TH>(updated_skeleton, leaf_modifications)
67+
FilledTreeImpl::create_with_existing_leaves::<TH>(updated_skeleton, leaf_modifications)
6768
.await
6869
.expect("Failed to create the filled tree")
6970
}
7071

7172
pub async fn single_tree_flow_test<
72-
L: LeafWithEmptyKeyContext + 'static,
73+
L: Leaf + 'static,
74+
Layout: for<'a> NodeLayout<'a, L> + 'static,
7375
TH: TreeHashFunction<L> + 'static,
7476
>(
7577
leaf_modifications: LeafModifications<L>,
7678
storage: &mut MapStorage,
7779
root_hash: HashOutput,
7880
config: impl OriginalSkeletonTreeConfig,
81+
// TODO(Ariel): Move trie_type to the config trait or to the leaf type.
82+
trie_type: TrieType,
7983
) -> String {
8084
// Move from leaf number to actual index.
8185
let leaf_modifications = leaf_modifications
8286
.into_iter()
8387
.map(|(k, v)| (NodeIndex::FIRST_LEAF + k, v))
8488
.collect::<LeafModifications<L>>();
8589

86-
let filled_tree =
87-
tree_computation_flow::<L, TH>(leaf_modifications, storage, root_hash, config).await;
90+
let key_context = Layout::generate_key_context(trie_type);
91+
let filled_tree = tree_computation_flow::<L, Layout, TH>(
92+
leaf_modifications,
93+
storage,
94+
root_hash,
95+
config,
96+
&key_context,
97+
)
98+
.await;
8899

89100
let hash_result = filled_tree.get_root_hash();
90101

@@ -93,7 +104,7 @@ pub async fn single_tree_flow_test<
93104
let json_hash = &json!(hash_result.0.to_hex_string());
94105
result_map.insert("root_hash", json_hash);
95106
// Serlialize the storage modifications.
96-
let json_storage = &json!(filled_tree.serialize(&EmptyKeyContext).unwrap());
107+
let json_storage = &json!(filled_tree.serialize::<L, Layout>(&key_context).unwrap());
97108
result_map.insert("storage_changes", json_storage);
98109
serde_json::to_string(&result_map).expect("serialization failed")
99110
}

crates/starknet_committer/src/db/facts_db/db.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,12 +130,21 @@ impl<S: Storage> ForestWriter for FactsDb<S> {
130130

131131
// Storage tries.
132132
for tree in filled_forest.storage_tries.values() {
133-
serialized_forest.extend(tree.serialize(&EmptyKeyContext)?);
133+
serialized_forest
134+
.extend(tree.serialize::<StarknetStorageValue, FactsNodeLayout>(&EmptyKeyContext)?);
134135
}
135136

136137
// Contracts and classes tries.
137-
serialized_forest.extend(filled_forest.contracts_trie.serialize(&EmptyKeyContext)?);
138-
serialized_forest.extend(filled_forest.classes_trie.serialize(&EmptyKeyContext)?);
138+
serialized_forest.extend(
139+
filled_forest
140+
.contracts_trie
141+
.serialize::<ContractState, FactsNodeLayout>(&EmptyKeyContext)?,
142+
);
143+
serialized_forest.extend(
144+
filled_forest
145+
.classes_trie
146+
.serialize::<CompiledClassHash, FactsNodeLayout>(&EmptyKeyContext)?,
147+
);
139148

140149
Ok(serialized_forest)
141150
}

crates/starknet_committer/src/db/index_db/db.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use starknet_patricia::patricia_merkle_tree::filled_tree::tree::FilledTree;
99
use starknet_patricia::patricia_merkle_tree::node_data::leaf::{Leaf, LeafModifications};
1010
use starknet_patricia::patricia_merkle_tree::types::NodeIndex;
1111
use starknet_patricia::patricia_merkle_tree::updated_skeleton_tree::hash_function::TreeHashFunction;
12-
use starknet_patricia_storage::db_object::{DBObject, EmptyKeyContext, HasStaticPrefix};
12+
use starknet_patricia_storage::db_object::{DBObject, HasStaticPrefix};
1313
use starknet_patricia_storage::errors::SerializationResult;
1414
use starknet_patricia_storage::storage_trait::{DbHashMap, DbKey, Storage};
1515

@@ -129,13 +129,25 @@ impl<S: Storage> ForestWriter for IndexDb<S> {
129129
let mut serialized_forest = DbHashMap::new();
130130

131131
// TODO(Ariel): use a different key context when FilledForest is generic over leaf types.
132-
for tree in filled_forest.storage_tries.values() {
133-
serialized_forest.extend(tree.serialize(&EmptyKeyContext)?);
132+
for (contract_address, tree) in &filled_forest.storage_tries {
133+
serialized_forest.extend(
134+
tree.serialize::<IndexLayoutStarknetStorageValue, IndexNodeLayout>(
135+
&TrieType::StorageTrie(*contract_address),
136+
)?,
137+
);
134138
}
135139

136140
// Contracts and classes tries.
137-
serialized_forest.extend(filled_forest.contracts_trie.serialize(&EmptyKeyContext)?);
138-
serialized_forest.extend(filled_forest.classes_trie.serialize(&EmptyKeyContext)?);
141+
serialized_forest.extend(
142+
filled_forest
143+
.contracts_trie
144+
.serialize::<IndexLayoutContractState, IndexNodeLayout>(&TrieType::ContractsTrie)?,
145+
);
146+
serialized_forest.extend(
147+
filled_forest.classes_trie.serialize::<IndexLayoutCompiledClassHash, IndexNodeLayout>(
148+
&TrieType::ClassesTrie,
149+
)?,
150+
);
139151

140152
Ok(serialized_forest)
141153
}

crates/starknet_committer_and_os_cli/benches/main.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use std::collections::HashMap;
1212
use criterion::{criterion_group, criterion_main, BatchSize, Criterion};
1313
use starknet_committer::block_committer::input::StarknetStorageValue;
1414
use starknet_committer::db::external_test_utils::tree_computation_flow;
15+
use starknet_committer::db::facts_db::db::FactsNodeLayout;
1516
use starknet_committer::hash_function::hash::TreeHashFunctionImpl;
1617
use starknet_committer::patricia_merkle_tree::tree::OriginalSkeletonTrieConfig;
1718
use starknet_committer_and_os_cli::committer_cli::commands::commit;
@@ -43,14 +44,17 @@ pub fn single_tree_flow_benchmark(criterion: &mut Criterion) {
4344
benchmark.iter_batched(
4445
|| leaf_modifications.clone(),
4546
|leaf_modifications_input| {
46-
runtime.block_on(
47-
tree_computation_flow::<StarknetStorageValue, TreeHashFunctionImpl>(
48-
leaf_modifications_input,
49-
&mut storage,
50-
root_hash,
51-
OriginalSkeletonTrieConfig::new_for_classes_or_storage_trie(false),
52-
),
53-
);
47+
runtime.block_on(tree_computation_flow::<
48+
StarknetStorageValue,
49+
FactsNodeLayout,
50+
TreeHashFunctionImpl,
51+
>(
52+
leaf_modifications_input,
53+
&mut storage,
54+
root_hash,
55+
OriginalSkeletonTrieConfig::new_for_classes_or_storage_trie(false),
56+
&EmptyKeyContext,
57+
));
5458
},
5559
BatchSize::LargeInput,
5660
)

crates/starknet_committer_and_os_cli/src/committer_cli/tests/python_tests.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use starknet_committer::block_committer::input::{
1212
};
1313
use starknet_committer::block_committer::random_structs::DummyRandomValue;
1414
use starknet_committer::db::external_test_utils::single_tree_flow_test;
15+
use starknet_committer::db::facts_db::db::FactsNodeLayout;
1516
use starknet_committer::forest::filled_forest::FilledForest;
1617
use starknet_committer::hash_function::hash::{
1718
TreeHashFunctionImpl,
@@ -21,6 +22,7 @@ use starknet_committer::hash_function::hash::{
2122
use starknet_committer::patricia_merkle_tree::leaf::leaf_impl::ContractState;
2223
use starknet_committer::patricia_merkle_tree::tree::OriginalSkeletonTrieConfig;
2324
use starknet_committer::patricia_merkle_tree::types::CompiledClassHash;
25+
use starknet_patricia::db_layout::TrieType;
2426
use starknet_patricia::patricia_merkle_tree::filled_tree::node::FactDbFilledNode;
2527
use starknet_patricia::patricia_merkle_tree::node_data::inner_node::{
2628
BinaryData,
@@ -163,11 +165,16 @@ impl PythonTestRunner for CommitterPythonTestRunner {
163165
let TreeFlowInput { leaf_modifications, mut storage, root_hash } =
164166
serde_json::from_str(Self::non_optional_input(input)?)?;
165167
// 2. Run the test.
166-
let output = single_tree_flow_test::<StarknetStorageValue, TreeHashFunctionImpl>(
168+
let output = single_tree_flow_test::<
169+
StarknetStorageValue,
170+
FactsNodeLayout,
171+
TreeHashFunctionImpl,
172+
>(
167173
leaf_modifications,
168174
&mut storage,
169175
root_hash,
170176
OriginalSkeletonTrieConfig::new_for_classes_or_storage_trie(false),
177+
TrieType::StorageTrie(ContractAddress::from(1_u128)),
171178
)
172179
.await;
173180
// 3. Serialize and return output.

crates/starknet_committer_and_os_cli/src/committer_cli/tests/regression_tests.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@ use std::fs;
44
use clap::Error;
55
use serde::{Deserialize, Deserializer};
66
use serde_json::{Map, Value};
7+
use starknet_api::core::ContractAddress;
78
use starknet_committer::block_committer::input::StarknetStorageValue;
89
use starknet_committer::db::external_test_utils::single_tree_flow_test;
10+
use starknet_committer::db::facts_db::db::FactsNodeLayout;
911
use starknet_committer::hash_function::hash::TreeHashFunctionImpl;
1012
use starknet_committer::patricia_merkle_tree::tree::OriginalSkeletonTrieConfig;
13+
use starknet_patricia::db_layout::TrieType;
1114
use tempfile::NamedTempFile;
1215

1316
use crate::committer_cli::commands::commit;
@@ -106,13 +109,15 @@ pub async fn test_regression_single_tree() {
106109

107110
let start = std::time::Instant::now();
108111
// Benchmark the single tree flow test.
109-
let output = single_tree_flow_test::<StarknetStorageValue, TreeHashFunctionImpl>(
110-
leaf_modifications,
111-
&mut storage,
112-
root_hash,
113-
OriginalSkeletonTrieConfig::new_for_classes_or_storage_trie(false),
114-
)
115-
.await;
112+
let output =
113+
single_tree_flow_test::<StarknetStorageValue, FactsNodeLayout, TreeHashFunctionImpl>(
114+
leaf_modifications,
115+
&mut storage,
116+
root_hash,
117+
OriginalSkeletonTrieConfig::new_for_classes_or_storage_trie(false),
118+
TrieType::StorageTrie(ContractAddress::from(1_u128)),
119+
)
120+
.await;
116121
let execution_time = std::time::Instant::now() - start;
117122

118123
// Assert correctness of the output of the single tree flow test.

0 commit comments

Comments
 (0)