Skip to content

Commit 096619a

Browse files
starknet_committer: parallel reads using unordered futures
1 parent e819a39 commit 096619a

File tree

3 files changed

+65
-0
lines changed

3 files changed

+65
-0
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/starknet_committer/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ apollo_config.workspace = true
1414
async-trait.workspace = true
1515
derive_more = { workspace = true, features = ["as_ref", "from", "into"] }
1616
ethnum.workspace = true
17+
futures.workspace = true
1718
hex.workspace = true
1819
pretty_assertions.workspace = true
1920
rand.workspace = true

crates/starknet_committer/src/db/trie_traversal.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::borrow::Borrow;
22
use std::collections::HashMap;
33
use std::fmt::Debug;
44

5+
use futures::stream::{FuturesUnordered, StreamExt};
56
use starknet_api::core::ContractAddress;
67
use starknet_api::hash::HashOutput;
78
use starknet_patricia::db_layout::{NodeLayout, NodeLayoutFor};
@@ -459,3 +460,65 @@ where
459460
}
460461
Ok(storage_tries)
461462
}
463+
464+
// TODO(Nimrod): Remove the `allow(dead_code)` once we use this function.
465+
#[allow(dead_code)]
466+
async fn create_storage_tries_concurrently<'a, Layout: NodeLayoutFor<StarknetStorageValue>>(
467+
storage: &impl Storage,
468+
actual_storage_updates: &HashMap<ContractAddress, LeafModifications<StarknetStorageValue>>,
469+
original_contracts_trie_leaves: &HashMap<NodeIndex, ContractState>,
470+
config: &ReaderConfig,
471+
storage_tries_sorted_indices: &HashMap<ContractAddress, SortedLeafIndices<'a>>,
472+
) -> ForestResult<HashMap<ContractAddress, OriginalSkeletonTreeImpl<'a>>>
473+
where
474+
<Layout as NodeLayoutFor<StarknetStorageValue>>::DbLeaf:
475+
HasStaticPrefix<KeyContext = ContractAddress>,
476+
{
477+
let mut futures = FuturesUnordered::new();
478+
let mut storage_tries = HashMap::new();
479+
480+
let trie_config = OriginalSkeletonTrieConfig::new_for_classes_or_storage_trie(
481+
config.warn_on_trivial_modifications(),
482+
);
483+
for (address, updates) in actual_storage_updates {
484+
// Extract data needed for this contract.
485+
let sorted_leaf_indices = *storage_tries_sorted_indices
486+
.get(address)
487+
.ok_or(ForestError::MissingSortedLeafIndices(*address))?;
488+
let contract_state = original_contracts_trie_leaves
489+
.get(&contract_address_into_node_index(address))
490+
.ok_or(ForestError::MissingContractCurrentState(*address))?;
491+
let cloned_trie_config = trie_config.clone();
492+
493+
// TODO(Ariel): Change `LeafModifications` in `actual_storage_updates` to be an
494+
// iterator over borrowed data so that the conversion below is costless.
495+
let leaf_modifications: HashMap<
496+
NodeIndex,
497+
<Layout as NodeLayoutFor<StarknetStorageValue>>::DbLeaf,
498+
> = updates.iter().map(|(idx, value)| (*idx, Layout::DbLeaf::from(*value))).collect();
499+
500+
// Create the future - tokio will poll all futures concurrently.
501+
futures.push(async move {
502+
let prevoius_leaves = None;
503+
let original_skeleton = create_original_skeleton_tree::<Layout::DbLeaf, Layout>(
504+
storage,
505+
contract_state.storage_root_hash,
506+
sorted_leaf_indices,
507+
&cloned_trie_config,
508+
&leaf_modifications,
509+
prevoius_leaves,
510+
address,
511+
)
512+
.await?;
513+
Ok::<_, ForestError>((address, original_skeleton))
514+
});
515+
}
516+
517+
// Collect all results as they complete.
518+
while let Some(result) = futures.next().await {
519+
let (address, original_skeleton) = result?;
520+
storage_tries.insert(*address, original_skeleton);
521+
}
522+
523+
Ok(storage_tries)
524+
}

0 commit comments

Comments
 (0)