starknet_committer: add index db#10685
Conversation
fd40107 to
787903d
Compare
d33ddf2 to
2d0a42b
Compare
2d0a42b to
ef53906
Compare
787903d to
d36e334
Compare
ef53906 to
d61f8a8
Compare
10ee434 to
97d3b36
Compare
d61f8a8 to
451b8f1
Compare
97d3b36 to
eb78b62
Compare
451b8f1 to
8d44e91
Compare
eb78b62 to
f176d41
Compare
d0285ee to
d220cc1
Compare
f176d41 to
e0517f7
Compare
d220cc1 to
8322fe7
Compare
4ce8285 to
a777ad0
Compare
8322fe7 to
f5a9fea
Compare
yoavGrs
left a comment
There was a problem hiding this comment.
@yoavGrs reviewed 4 files and all commit messages, and made 4 comments.
Reviewable status: all files reviewed, 4 unresolved discussions (waiting on @ArielElp and @nimrod-starkware).
a discussion (no related file):
These read & write implementations are similar to the facts layout.
What are the next steps?
Do you plan to define a default implementation with generic types?
Made some changes to justify the code duplication?
crates/starknet_committer/src/db/index_db/db.rs line 51 at r2 (raw file):
impl<'a, L: Leaf> NodeLayout<'a, L> for IndexNodeLayout where L: HasStaticPrefix<KeyContext = TrieType>,
non-blocking
Suggestion:
impl<'a, L> NodeLayout<'a, L> for IndexNodeLayout
where
L: Leaf + HasStaticPrefix<KeyContext = TrieType>,crates/starknet_committer/src/db/index_db/db.rs line 59 at r2 (raw file):
type SubTree = IndexLayoutSubTree<'a>; fn generate_key_context(trie_type: TrieType) -> <L as HasStaticPrefix>::KeyContext {
In both implementations, you do not generate (or calculate). WDYT?
Suggestion:
get_key_contextcrates/starknet_committer/src/db/index_db/db.rs line 85 at r2 (raw file):
forest_sorted_indices.contracts_trie_sorted_indices, ) .await?;
By adding such a get_state_roots function to the reader trait, can we set the read function as the default implementation?
Suggestion:
let state_roots = self.get_state_roots(context);
let (contracts_trie, original_contracts_trie_leaves) =
create_contracts_trie::<IndexLayoutContractState, IndexNodeLayout>(
&mut self.storage,
state_roots.contracts_trie_root_hash,
forest_sorted_indices.contracts_trie_sorted_indices,
)
.await?;
nimrod-starkware
left a comment
There was a problem hiding this comment.
@nimrod-starkware reviewed all commit messages and made 1 comment.
Reviewable status: all files reviewed, 5 unresolved discussions (waiting on @ArielElp).
crates/starknet_committer/src/db/index_db/db.rs line 109 at r2 (raw file):
)) } }
This looks almost like the ForestReader impl for FactsDb.
IIUC the only difference are the types.
I thought to associate the concrete leaf types with the ForestReader trait and add (and use) default implementation for fn read. WDYT?
Code quote:
// TODO(Ariel): define an IndexDbInitialRead empty type, and check whether each tree is empty inside
// create_xxx_trie.
#[async_trait]
impl<S: Storage> ForestReader<FactsDbInitialRead> for IndexDb<S> {
/// Creates an original skeleton forest that includes the storage tries of the modified
/// contracts, the classes trie and the contracts trie. Additionally, returns the original
/// contract states that are needed to compute the contract state tree.
async fn read<'a>(
&mut self,
context: FactsDbInitialRead,
storage_updates: &'a HashMap<ContractAddress, LeafModifications<StarknetStorageValue>>,
classes_updates: &'a LeafModifications<CompiledClassHash>,
forest_sorted_indices: &'a ForestSortedIndices<'a>,
config: ReaderConfig,
) -> ForestResult<(OriginalSkeletonForest<'a>, HashMap<NodeIndex, ContractState>)> {
let (contracts_trie, original_contracts_trie_leaves) =
create_contracts_trie::<IndexLayoutContractState, IndexNodeLayout>(
&mut self.storage,
context.0.contracts_trie_root_hash,
forest_sorted_indices.contracts_trie_sorted_indices,
)
.await?;
let storage_tries =
create_storage_tries::<IndexLayoutStarknetStorageValue, IndexNodeLayout>(
&mut self.storage,
storage_updates,
&original_contracts_trie_leaves,
&config,
&forest_sorted_indices.storage_tries_sorted_indices,
)
.await?;
let classes_trie = create_classes_trie::<IndexLayoutCompiledClassHash, IndexNodeLayout>(
&mut self.storage,
classes_updates,
context.0.classes_trie_root_hash,
&config,
forest_sorted_indices.classes_trie_sorted_indices,
)
.await?;
Ok((
OriginalSkeletonForest { classes_trie, contracts_trie, storage_tries },
original_contracts_trie_leaves,
))
}
}
nimrod-starkware
left a comment
There was a problem hiding this comment.
@nimrod-starkware made 1 comment.
Reviewable status: all files reviewed, 5 unresolved discussions (waiting on @ArielElp).
crates/starknet_committer/src/db/index_db/db.rs line 109 at r2 (raw file):
Previously, nimrod-starkware wrote…
This looks almost like the
ForestReaderimpl forFactsDb.
IIUC the only difference are the types.
I thought to associate the concrete leaf types with theForestReadertrait and add (and use) default implementation forfn read. WDYT?
(obviously should not be done in this PR, if you think it's a good idea add a todo please)
ArielElp
left a comment
There was a problem hiding this comment.
@ArielElp made 3 comments and resolved 1 discussion.
Reviewable status: all files reviewed, 4 unresolved discussions (waiting on @dorimedini-starkware and @yoavGrs).
crates/starknet_committer/src/db/index_db/db.rs line 59 at r2 (raw file):
Previously, yoavGrs wrote…
In both implementations, you do not generate (or calculate). WDYT?
I prefer generate since this is THE place where we get it for the first time and then it's passed between all the internal functions
crates/starknet_committer/src/db/index_db/db.rs line 85 at r2 (raw file):
Previously, yoavGrs wrote…
By adding such a
get_state_rootsfunction to the reader trait, can we set the read function as the default implementation?
IMO this makes the trait more complicated and the benefit is not that large. I prefer the read_inner method with all the generics, but prefer keeping it as is compared to both. @dorimedini-starkware will be the judge
crates/starknet_committer/src/db/index_db/db.rs line 109 at r2 (raw file):
Previously, nimrod-starkware wrote…
(obviously should not be done in this PR, if you think it's a good idea add a todo please)
See comment above, relayed to @dorimedini-starkware's judgement
dorimedini-starkware
left a comment
There was a problem hiding this comment.
@dorimedini-starkware reviewed 4 files and all commit messages, and made 4 comments.
Reviewable status: all files reviewed, 6 unresolved discussions (waiting on @ArielElp, @nimrod-starkware, and @yoavGrs).
crates/starknet_committer/src/db/index_db/db.rs line 85 at r2 (raw file):
Previously, ArielElp wrote…
IMO this makes the trait more complicated and the benefit is not that large. I prefer the read_inner method with all the generics, but prefer keeping it as is compared to both. @dorimedini-starkware will be the judge
- indeed seems identical except for generics; why does it complicate the trait? generics list is longer?
- If we go for this change, I think this actually should be part of this Pr, so it's easy to see behavior change is minimal, rather than adding logic here and deleting it in a later PR
crates/starknet_committer/src/db/index_db/db.rs line 109 at r2 (raw file):
Previously, ArielElp wrote…
See comment above, relayed to @dorimedini-starkware's judgement
gave my two cents above
crates/starknet_committer/src/db/index_db/db.rs line 38 at r2 (raw file):
pub struct IndexDb<S: Storage> { pub storage: S,
better to block direct access in advance
Suggestion:
storage: S,crates/starknet_committer/src/db/index_db/db.rs line 135 at r2 (raw file):
.unwrap_or_else(|_| panic!("Write of {n_updates} new updates to storage failed")); n_updates }
these impls are also identical to the FactsDb implementation, why are specific impls needed?
Code quote:
fn serialize_forest(filled_forest: &FilledForest) -> SerializationResult<DbHashMap> {
let mut serialized_forest = DbHashMap::new();
// TODO(Ariel): use a different key context when FilledForest is generic over leaf types.
for tree in filled_forest.storage_tries.values() {
serialized_forest.extend(tree.serialize(&EmptyKeyContext)?);
}
// Contracts and classes tries.
serialized_forest.extend(filled_forest.contracts_trie.serialize(&EmptyKeyContext)?);
serialized_forest.extend(filled_forest.classes_trie.serialize(&EmptyKeyContext)?);
Ok(serialized_forest)
}
async fn write_updates(&mut self, updates: DbHashMap) -> usize {
let n_updates = updates.len();
self.storage
.mset(updates)
.await
.unwrap_or_else(|_| panic!("Write of {n_updates} new updates to storage failed"));
n_updates
}
dorimedini-starkware
left a comment
There was a problem hiding this comment.
@dorimedini-starkware reviewed 1 file and all commit messages.
Reviewable status: all files reviewed, 6 unresolved discussions (waiting on @ArielElp, @nimrod-starkware, and @yoavGrs).
ArielElp
left a comment
There was a problem hiding this comment.
@ArielElp made 5 comments.
Reviewable status: 3 of 6 files reviewed, 6 unresolved discussions (waiting on @dorimedini-starkware, @nimrod-starkware, and @yoavGrs).
a discussion (no related file):
Previously, yoavGrs wrote…
These read & write implementations are similar to the facts layout.
What are the next steps?Do you plan to define a default implementation with generic types?
Made some changes to justify the code duplication?
Done.
crates/starknet_committer/src/db/index_db/db.rs line 38 at r2 (raw file):
Previously, dorimedini-starkware wrote…
better to block direct access in advance
Done.
crates/starknet_committer/src/db/index_db/db.rs line 85 at r2 (raw file):
Previously, dorimedini-starkware wrote…
- indeed seems identical except for generics; why does it complicate the trait? generics list is longer?
- If we go for this change, I think this actually should be part of this Pr, so it's easy to see behavior change is minimal, rather than adding logic here and deleting it in a later PR
I went for not changing the trait and adding the generic forest_reader function, which is called from both reads. PTAL, looks good IMO. Relying on a helper inside the trait requires extracting storage from the reader which we probably don't want to do.
crates/starknet_committer/src/db/index_db/db.rs line 109 at r2 (raw file):
Previously, dorimedini-starkware wrote…
gave my two cents above
Done.
crates/starknet_committer/src/db/index_db/db.rs line 135 at r2 (raw file):
Previously, dorimedini-starkware wrote…
these impls are also identical to the FactsDb implementation, why are specific impls needed?
True, in the serialization PRs they will become different (in a similar way to reads, via the generics). Can we leave it as-is and tackle the serialization shared code in the serialization PR?
dorimedini-starkware
left a comment
There was a problem hiding this comment.
@dorimedini-starkware reviewed 3 files and all commit messages, and resolved 2 discussions.
Reviewable status: all files reviewed, 4 unresolved discussions (waiting on @nimrod-starkware and @yoavGrs).
nimrod-starkware
left a comment
There was a problem hiding this comment.
@nimrod-starkware made 1 comment and resolved 1 discussion.
Reviewable status: all files reviewed, 3 unresolved discussions (waiting on @yoavGrs).
dorimedini-starkware
left a comment
There was a problem hiding this comment.
Reviewable status: all files reviewed, 3 unresolved discussions (waiting on @yoavGrs).
yoavGrs
left a comment
There was a problem hiding this comment.
@yoavGrs reviewed all commit messages, made 1 comment, and resolved 3 discussions.
Reviewable status:complete! all files reviewed, all discussions resolved (waiting on @ArielElp).
dorimedini-starkware
left a comment
There was a problem hiding this comment.
Reviewable status:
complete! all files reviewed, all discussions resolved (waiting on @ArielElp).

No description provided.