Skip to content

Commit c0770f7

Browse files
committed
starknet_committer: abstract original tree creation
1 parent 6d0d334 commit c0770f7

File tree

10 files changed

+243
-192
lines changed

10 files changed

+243
-192
lines changed

crates/starknet_committer/src/db/db_layout.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1+
use starknet_api::hash::HashOutput;
12
use starknet_patricia::patricia_merkle_tree::filled_tree::node::FilledNode;
23
use starknet_patricia::patricia_merkle_tree::node_data::leaf::Leaf;
34
use starknet_patricia::patricia_merkle_tree::traversal::SubTreeTrait;
4-
use starknet_patricia_storage::db_object::DBObject;
5+
use starknet_patricia::patricia_merkle_tree::types::{NodeIndex, SortedLeafIndices};
6+
use starknet_patricia_storage::db_object::{DBObject, HasStaticPrefix};
7+
8+
use crate::db::index_db::leaves::TrieType;
59

610
/// Specifies the trie db layout.
711
pub trait NodeLayout<'a, L: Leaf>
@@ -21,4 +25,12 @@ where
2125
NodeData = Self::NodeData,
2226
NodeDeserializeContext = Self::DeserializationContext,
2327
>;
28+
29+
fn create_subtree(
30+
sorted_leaf_indices: SortedLeafIndices<'a>,
31+
root_index: NodeIndex,
32+
root_hash: HashOutput,
33+
) -> Self::SubTree;
34+
35+
fn generate_key_context(trie_type: TrieType) -> <L as HasStaticPrefix>::KeyContext;
2436
}

crates/starknet_committer/src/db/external_test_utils.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ use starknet_patricia::patricia_merkle_tree::updated_skeleton_tree::tree::{
1818
use starknet_patricia_storage::db_object::{EmptyKeyContext, HasStaticPrefix};
1919
use starknet_patricia_storage::map_storage::MapStorage;
2020

21-
use crate::db::facts_db::create_facts_tree::create_original_skeleton_tree;
21+
use crate::db::facts_db::db::FactsNodeLayout;
22+
use crate::db::trie_traversal::create_original_skeleton_tree;
2223

2324
// TODO(Ariel, 14/12/2025): make this generic over the layout.
2425
pub async fn tree_computation_flow<L, TH>(
@@ -33,7 +34,7 @@ where
3334
{
3435
let mut sorted_leaf_indices: Vec<NodeIndex> = leaf_modifications.keys().copied().collect();
3536
let sorted_leaf_indices = SortedLeafIndices::new(&mut sorted_leaf_indices);
36-
let mut original_skeleton = create_original_skeleton_tree(
37+
let mut original_skeleton = create_original_skeleton_tree::<L, FactsNodeLayout>(
3738
storage,
3839
root_hash,
3940
sorted_leaf_indices,

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

Lines changed: 8 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -9,59 +9,27 @@ use starknet_patricia::patricia_merkle_tree::original_skeleton_tree::tree::{
99
};
1010
use starknet_patricia::patricia_merkle_tree::traversal::SubTreeTrait;
1111
use starknet_patricia::patricia_merkle_tree::types::{NodeIndex, SortedLeafIndices};
12-
use starknet_patricia_storage::db_object::HasStaticPrefix;
12+
use starknet_patricia_storage::db_object::{EmptyKeyContext, HasStaticPrefix};
1313
use starknet_patricia_storage::storage_trait::Storage;
1414

1515
use crate::db::facts_db::db::FactsNodeLayout;
1616
use crate::db::facts_db::types::FactsSubTree;
17-
use crate::db::trie_traversal::{fetch_nodes, log_warning_for_empty_leaves};
17+
use crate::db::trie_traversal::fetch_nodes;
1818
use crate::patricia_merkle_tree::tree::OriginalSkeletonTrieDontCompareConfig;
1919

2020
#[cfg(test)]
2121
#[path = "create_facts_tree_test.rs"]
2222
pub mod create_facts_tree_test;
2323

24-
pub async fn create_original_skeleton_tree<'a, L: Leaf>(
25-
storage: &mut impl Storage,
26-
root_hash: HashOutput,
27-
sorted_leaf_indices: SortedLeafIndices<'a>,
28-
config: &impl OriginalSkeletonTreeConfig,
29-
leaf_modifications: &LeafModifications<L>,
30-
key_context: &<L as HasStaticPrefix>::KeyContext,
31-
) -> OriginalSkeletonTreeResult<OriginalSkeletonTreeImpl<'a>> {
32-
if sorted_leaf_indices.is_empty() {
33-
return Ok(OriginalSkeletonTreeImpl::create_unmodified(root_hash));
34-
}
35-
if root_hash == HashOutput::ROOT_OF_EMPTY_TREE {
36-
log_warning_for_empty_leaves(
37-
sorted_leaf_indices.get_indices(),
38-
leaf_modifications,
39-
config,
40-
)?;
41-
return Ok(OriginalSkeletonTreeImpl::create_empty(sorted_leaf_indices));
42-
}
43-
let main_subtree = FactsSubTree::create(sorted_leaf_indices, NodeIndex::ROOT, root_hash);
44-
let mut skeleton_tree = OriginalSkeletonTreeImpl { nodes: HashMap::new(), sorted_leaf_indices };
45-
fetch_nodes::<L, FactsNodeLayout>(
46-
&mut skeleton_tree,
47-
vec![main_subtree],
48-
storage,
49-
leaf_modifications,
50-
config,
51-
None,
52-
key_context,
53-
)
54-
.await?;
55-
Ok(skeleton_tree)
56-
}
57-
58-
pub async fn create_original_skeleton_tree_and_get_previous_leaves<'a, L: Leaf>(
24+
pub async fn create_original_skeleton_tree_and_get_previous_leaves<
25+
'a,
26+
L: Leaf + HasStaticPrefix<KeyContext = EmptyKeyContext>,
27+
>(
5928
storage: &mut impl Storage,
6029
root_hash: HashOutput,
6130
sorted_leaf_indices: SortedLeafIndices<'a>,
6231
leaf_modifications: &LeafModifications<L>,
6332
config: &impl OriginalSkeletonTreeConfig,
64-
key_context: &<L as HasStaticPrefix>::KeyContext,
6533
) -> OriginalSkeletonTreeResult<(OriginalSkeletonTreeImpl<'a>, HashMap<NodeIndex, L>)> {
6634
if sorted_leaf_indices.is_empty() {
6735
let unmodified = OriginalSkeletonTreeImpl::create_unmodified(root_hash);
@@ -83,7 +51,7 @@ pub async fn create_original_skeleton_tree_and_get_previous_leaves<'a, L: Leaf>(
8351
leaf_modifications,
8452
config,
8553
Some(&mut leaves),
86-
key_context,
54+
&EmptyKeyContext,
8755
)
8856
.await?;
8957
Ok((skeleton_tree, leaves))
@@ -92,11 +60,10 @@ pub async fn create_original_skeleton_tree_and_get_previous_leaves<'a, L: Leaf>(
9260
/// Prepares the OS inputs by fetching paths to the given leaves (i.e. their induced Skeleton tree).
9361
/// Note that ATM, the Rust committer does not manage history and is not used for storage proofs;
9462
/// Thus, this function assumes facts layout.
95-
pub async fn get_leaves<'a, L: Leaf>(
63+
pub async fn get_leaves<'a, L: Leaf + HasStaticPrefix<KeyContext = EmptyKeyContext>>(
9664
storage: &mut impl Storage,
9765
root_hash: HashOutput,
9866
sorted_leaf_indices: SortedLeafIndices<'a>,
99-
key_context: &<L as HasStaticPrefix>::KeyContext,
10067
) -> OriginalSkeletonTreeResult<HashMap<NodeIndex, L>> {
10168
let config = OriginalSkeletonTrieDontCompareConfig;
10269
let leaf_modifications = LeafModifications::new();
@@ -106,7 +73,6 @@ pub async fn get_leaves<'a, L: Leaf>(
10673
sorted_leaf_indices,
10774
&leaf_modifications,
10875
&config,
109-
key_context,
11076
)
11177
.await?;
11278
Ok(previous_leaves)

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ use starknet_patricia_storage::map_storage::MapStorage;
2222
use starknet_patricia_storage::storage_trait::{DbHashMap, DbKey, DbValue};
2323
use starknet_types_core::felt::Felt;
2424

25-
use crate::db::facts_db::create_facts_tree::create_original_skeleton_tree;
25+
use crate::db::facts_db::db::FactsNodeLayout;
26+
use crate::db::trie_traversal::create_original_skeleton_tree;
2627
use crate::patricia_merkle_tree::tree::OriginalSkeletonTrieConfig;
2728

2829
#[tokio::test]
@@ -211,7 +212,7 @@ async fn test_create_tree(
211212
let config = OriginalSkeletonTrieConfig::new(compare_modified_leaves);
212213
let mut sorted_leaf_indices: Vec<NodeIndex> = leaf_modifications.keys().copied().collect();
213214
let sorted_leaf_indices = SortedLeafIndices::new(&mut sorted_leaf_indices);
214-
let skeleton_tree = create_original_skeleton_tree(
215+
let skeleton_tree = create_original_skeleton_tree::<MockLeaf, FactsNodeLayout>(
215216
&mut storage,
216217
root_hash,
217218
sorted_leaf_indices,

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

Lines changed: 41 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ use starknet_api::hash::HashOutput;
66
use starknet_patricia::patricia_merkle_tree::filled_tree::node_serde::FactNodeDeserializationContext;
77
use starknet_patricia::patricia_merkle_tree::filled_tree::tree::FilledTree;
88
use starknet_patricia::patricia_merkle_tree::node_data::leaf::{Leaf, LeafModifications};
9-
use starknet_patricia::patricia_merkle_tree::original_skeleton_tree::tree::OriginalSkeletonTreeImpl;
9+
use starknet_patricia::patricia_merkle_tree::traversal::SubTreeTrait;
1010
use starknet_patricia::patricia_merkle_tree::types::{NodeIndex, SortedLeafIndices};
11-
use starknet_patricia_storage::db_object::EmptyKeyContext;
11+
use starknet_patricia_storage::db_object::{EmptyKeyContext, HasStaticPrefix};
1212
use starknet_patricia_storage::errors::SerializationResult;
1313
use starknet_patricia_storage::map_storage::MapStorage;
1414
use starknet_patricia_storage::storage_trait::{
@@ -19,25 +19,16 @@ use starknet_patricia_storage::storage_trait::{
1919
Storage,
2020
};
2121

22-
use crate::block_committer::input::{
23-
contract_address_into_node_index,
24-
Config,
25-
FactsDbInitialRead,
26-
ReaderConfig,
27-
StarknetStorageValue,
28-
};
22+
use crate::block_committer::input::{FactsDbInitialRead, ReaderConfig, StarknetStorageValue};
2923
use crate::db::db_layout::NodeLayout;
30-
use crate::db::facts_db::create_facts_tree::{
31-
create_original_skeleton_tree,
32-
create_original_skeleton_tree_and_get_previous_leaves,
33-
};
3424
use crate::db::facts_db::types::FactsSubTree;
3525
use crate::db::forest_trait::{ForestMetadata, ForestMetadataType, ForestReader, ForestWriter};
26+
use crate::db::index_db::leaves::TrieType;
27+
use crate::db::trie_traversal::{create_classes_trie, create_contracts_trie, create_storage_tries};
3628
use crate::forest::filled_forest::FilledForest;
37-
use crate::forest::forest_errors::{ForestError, ForestResult};
29+
use crate::forest::forest_errors::ForestResult;
3830
use crate::forest::original_skeleton_forest::{ForestSortedIndices, OriginalSkeletonForest};
3931
use crate::patricia_merkle_tree::leaf::leaf_impl::ContractState;
40-
use crate::patricia_merkle_tree::tree::OriginalSkeletonTrieConfig;
4132
use crate::patricia_merkle_tree::types::CompiledClassHash;
4233

4334
/// Facts DB node layout.
@@ -47,12 +38,27 @@ use crate::patricia_merkle_tree::types::CompiledClassHash;
4738
/// have the db keys of its children.
4839
pub struct FactsNodeLayout {}
4940

50-
impl<'a, L: Leaf> NodeLayout<'a, L> for FactsNodeLayout {
41+
impl<'a, L: Leaf> NodeLayout<'a, L> for FactsNodeLayout
42+
where
43+
L: HasStaticPrefix<KeyContext = EmptyKeyContext>,
44+
{
5145
type NodeData = HashOutput;
5246

5347
type DeserializationContext = FactNodeDeserializationContext;
5448

5549
type SubTree = FactsSubTree<'a>;
50+
51+
fn create_subtree(
52+
sorted_leaf_indices: SortedLeafIndices<'a>,
53+
root_index: NodeIndex,
54+
root_hash: HashOutput,
55+
) -> Self::SubTree {
56+
FactsSubTree::create(sorted_leaf_indices, root_index, root_hash)
57+
}
58+
59+
fn generate_key_context(_trie_type: TrieType) -> <L as HasStaticPrefix>::KeyContext {
60+
EmptyKeyContext
61+
}
5662
}
5763

5864
pub struct FactsDb<S: Storage> {
@@ -68,75 +74,6 @@ impl<S: Storage> FactsDb<S> {
6874
pub fn new(storage: S) -> Self {
6975
Self { storage }
7076
}
71-
72-
/// Creates the contracts trie original skeleton.
73-
/// Also returns the previous contracts state of the modified contracts.
74-
async fn create_contracts_trie<'a>(
75-
&mut self,
76-
contracts_trie_root_hash: HashOutput,
77-
contracts_trie_sorted_indices: SortedLeafIndices<'a>,
78-
) -> ForestResult<(OriginalSkeletonTreeImpl<'a>, HashMap<NodeIndex, ContractState>)> {
79-
Ok(create_original_skeleton_tree_and_get_previous_leaves(
80-
&mut self.storage,
81-
contracts_trie_root_hash,
82-
contracts_trie_sorted_indices,
83-
&HashMap::new(),
84-
&OriginalSkeletonTrieConfig::new(true),
85-
&EmptyKeyContext,
86-
)
87-
.await?)
88-
}
89-
90-
async fn create_storage_tries<'a>(
91-
&mut self,
92-
actual_storage_updates: &HashMap<ContractAddress, LeafModifications<StarknetStorageValue>>,
93-
original_contracts_trie_leaves: &HashMap<NodeIndex, ContractState>,
94-
config: &impl Config,
95-
storage_tries_sorted_indices: &HashMap<ContractAddress, SortedLeafIndices<'a>>,
96-
) -> ForestResult<HashMap<ContractAddress, OriginalSkeletonTreeImpl<'a>>> {
97-
let mut storage_tries = HashMap::new();
98-
for (address, updates) in actual_storage_updates {
99-
let sorted_leaf_indices = storage_tries_sorted_indices
100-
.get(address)
101-
.ok_or(ForestError::MissingSortedLeafIndices(*address))?;
102-
let contract_state = original_contracts_trie_leaves
103-
.get(&contract_address_into_node_index(address))
104-
.ok_or(ForestError::MissingContractCurrentState(*address))?;
105-
let config = OriginalSkeletonTrieConfig::new(config.warn_on_trivial_modifications());
106-
107-
let original_skeleton = create_original_skeleton_tree(
108-
&mut self.storage,
109-
contract_state.storage_root_hash,
110-
*sorted_leaf_indices,
111-
&config,
112-
updates,
113-
&EmptyKeyContext,
114-
)
115-
.await?;
116-
storage_tries.insert(*address, original_skeleton);
117-
}
118-
Ok(storage_tries)
119-
}
120-
121-
async fn create_classes_trie<'a>(
122-
&mut self,
123-
actual_classes_updates: &LeafModifications<CompiledClassHash>,
124-
classes_trie_root_hash: HashOutput,
125-
config: &impl Config,
126-
contracts_trie_sorted_indices: SortedLeafIndices<'a>,
127-
) -> ForestResult<OriginalSkeletonTreeImpl<'a>> {
128-
let config = OriginalSkeletonTrieConfig::new(config.warn_on_trivial_modifications());
129-
130-
Ok(create_original_skeleton_tree(
131-
&mut self.storage,
132-
classes_trie_root_hash,
133-
contracts_trie_sorted_indices,
134-
&config,
135-
actual_classes_updates,
136-
&EmptyKeyContext,
137-
)
138-
.await?)
139-
}
14077
}
14178

14279
impl FactsDb<MapStorage> {
@@ -158,28 +95,29 @@ impl<S: Storage> ForestReader<FactsDbInitialRead> for FactsDb<S> {
15895
forest_sorted_indices: &'a ForestSortedIndices<'a>,
15996
config: ReaderConfig,
16097
) -> ForestResult<(OriginalSkeletonForest<'a>, HashMap<NodeIndex, ContractState>)> {
161-
let (contracts_trie, original_contracts_trie_leaves) = self
162-
.create_contracts_trie(
98+
let (contracts_trie, original_contracts_trie_leaves) =
99+
create_contracts_trie::<ContractState, FactsNodeLayout>(
100+
&mut self.storage,
163101
context.0.contracts_trie_root_hash,
164102
forest_sorted_indices.contracts_trie_sorted_indices,
165103
)
166104
.await?;
167-
let storage_tries = self
168-
.create_storage_tries(
169-
storage_updates,
170-
&original_contracts_trie_leaves,
171-
&config,
172-
&forest_sorted_indices.storage_tries_sorted_indices,
173-
)
174-
.await?;
175-
let classes_trie = self
176-
.create_classes_trie(
177-
classes_updates,
178-
context.0.classes_trie_root_hash,
179-
&config,
180-
forest_sorted_indices.classes_trie_sorted_indices,
181-
)
182-
.await?;
105+
let storage_tries = create_storage_tries::<StarknetStorageValue, FactsNodeLayout>(
106+
&mut self.storage,
107+
storage_updates,
108+
&original_contracts_trie_leaves,
109+
&config,
110+
&forest_sorted_indices.storage_tries_sorted_indices,
111+
)
112+
.await?;
113+
let classes_trie = create_classes_trie::<CompiledClassHash, FactsNodeLayout>(
114+
&mut self.storage,
115+
classes_updates,
116+
context.0.classes_trie_root_hash,
117+
&config,
118+
forest_sorted_indices.classes_trie_sorted_indices,
119+
)
120+
.await?;
183121

184122
Ok((
185123
OriginalSkeletonForest { classes_trie, contracts_trie, storage_tries },

0 commit comments

Comments
 (0)