Skip to content

Commit f629d46

Browse files
committed
starknet_committer: define fetch_contract_storage_paths_concurrently
1 parent 74043bf commit f629d46

1 file changed

Lines changed: 115 additions & 0 deletions

File tree

crates/starknet_committer/src/db/trie_traversal.rs

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ use tracing::warn;
4545

4646
use crate::block_committer::input::{
4747
contract_address_into_node_index,
48+
try_node_index_into_contract_address,
4849
ReaderConfig,
4950
StarknetStorageValue,
5051
};
@@ -924,6 +925,120 @@ where
924925
storage.gather(tasks).await.into_iter().collect()
925926
}
926927

928+
/// Fetches Patricia proofs for the storage tries. If the storage has a [GatherableStorage] version,
929+
/// then the paths are fetched concurrently. Otherwise, they are fetched sequentially.
930+
pub(crate) async fn fetch_contract_storage_paths<StorageLayout, ContractLeaf>(
931+
storage: &mut impl ReadOnlyStorage,
932+
contract_storage_sorted_leaf_indices: &HashMap<NodeIndex, SortedLeafIndices<'_>>,
933+
contract_leaves: &HashMap<NodeIndex, ContractLeaf>,
934+
) -> TraversalResult<HashMap<ContractAddress, PreimageMap>>
935+
where
936+
StorageLayout: NodeLayoutFor<StarknetStorageValue> + Send + 'static,
937+
<StorageLayout as NodeLayoutFor<StarknetStorageValue>>::DbLeaf:
938+
HasStaticPrefix<KeyContext = ContractAddress>,
939+
ContractLeaf: AsRef<ContractState>,
940+
{
941+
if let Some(gatherable_storage) = storage.as_gatherable_storage() {
942+
return fetch_contract_storage_paths_concurrently::<_, StorageLayout, ContractLeaf>(
943+
gatherable_storage,
944+
contract_storage_sorted_leaf_indices,
945+
contract_leaves,
946+
)
947+
.await;
948+
}
949+
fetch_contract_storage_paths_sequentially::<StorageLayout, ContractLeaf>(
950+
storage,
951+
contract_storage_sorted_leaf_indices,
952+
contract_leaves,
953+
)
954+
.await
955+
}
956+
957+
/// Sequentially fetches Patricia proofs for the storage tries.
958+
async fn fetch_contract_storage_paths_sequentially<StorageLayout, ContractLeaf>(
959+
storage: &mut impl ReadOnlyStorage,
960+
contract_storage_sorted_leaf_indices: &HashMap<NodeIndex, SortedLeafIndices<'_>>,
961+
contract_leaves: &HashMap<NodeIndex, ContractLeaf>,
962+
) -> TraversalResult<HashMap<ContractAddress, PreimageMap>>
963+
where
964+
StorageLayout: NodeLayoutFor<StarknetStorageValue> + Send + 'static,
965+
<StorageLayout as NodeLayoutFor<StarknetStorageValue>>::DbLeaf:
966+
HasStaticPrefix<KeyContext = ContractAddress>,
967+
ContractLeaf: AsRef<ContractState>,
968+
{
969+
let mut contracts_trie_storage_proofs =
970+
HashMap::with_capacity(contract_storage_sorted_leaf_indices.len());
971+
972+
for (idx, sorted_leaf_indices) in contract_storage_sorted_leaf_indices {
973+
let contract_address = try_node_index_into_contract_address(idx).unwrap_or_else(|_| {
974+
panic!(
975+
"Converting leaf NodeIndex to ContractAddress should succeed; failed to convert \
976+
{idx:?}."
977+
)
978+
});
979+
980+
// The contract address might not exist in the contracts trie in the following cases:
981+
// 1. We are looking at the previous tree and the contract is new.
982+
// 2. We are looking at the new tree and the contract is deleted (revert).
983+
// In either case, the storage trie of this contract is empty, so there is nothing to
984+
// prove regarding the contract storage.
985+
let Some(storage_root_hash) =
986+
contract_leaves.get(idx).map(|leaf| leaf.as_ref().storage_root_hash)
987+
else {
988+
continue;
989+
};
990+
991+
let leaves = None;
992+
let proof = fetch_patricia_paths::<StorageLayout::DbLeaf, StorageLayout>(
993+
storage,
994+
storage_root_hash,
995+
*sorted_leaf_indices,
996+
leaves,
997+
&contract_address,
998+
)
999+
.await?;
1000+
contracts_trie_storage_proofs.insert(contract_address, proof);
1001+
}
1002+
1003+
Ok(contracts_trie_storage_proofs)
1004+
}
1005+
1006+
/// Concurrently fetches Patricia proofs for the storage tries.
1007+
async fn fetch_contract_storage_paths_concurrently<S, StorageLayout, ContractLeaf>(
1008+
storage: &mut S,
1009+
contract_storage_sorted_leaf_indices: &HashMap<NodeIndex, SortedLeafIndices<'_>>,
1010+
contract_leaves: &HashMap<NodeIndex, ContractLeaf>,
1011+
) -> TraversalResult<HashMap<ContractAddress, PreimageMap>>
1012+
where
1013+
S: GatherableStorage,
1014+
StorageLayout: NodeLayoutFor<StarknetStorageValue> + Send + 'static,
1015+
<StorageLayout as NodeLayoutFor<StarknetStorageValue>>::DbLeaf:
1016+
HasStaticPrefix<KeyContext = ContractAddress>,
1017+
ContractLeaf: AsRef<ContractState>,
1018+
{
1019+
let mut tasks = Vec::new();
1020+
for (idx, sorted_leaf_indices) in contract_storage_sorted_leaf_indices {
1021+
let contract_address = try_node_index_into_contract_address(idx).unwrap_or_else(|_| {
1022+
panic!(
1023+
"Converting leaf NodeIndex to ContractAddress should succeed; failed to convert \
1024+
{idx:?}."
1025+
)
1026+
});
1027+
let Some(storage_root_hash) =
1028+
contract_leaves.get(idx).map(|leaf| leaf.as_ref().storage_root_hash)
1029+
else {
1030+
continue;
1031+
};
1032+
tasks.push(StoragePathsReadTask::<StorageLayout> {
1033+
address: contract_address,
1034+
storage_root_hash,
1035+
sorted_leaf_indices: *sorted_leaf_indices,
1036+
_layout: PhantomData,
1037+
});
1038+
}
1039+
storage.gather(tasks).await.into_iter().collect()
1040+
}
1041+
9271042
/// Helper function to create a storage trie for a single contract.
9281043
async fn create_storage_trie<'a, Layout: NodeLayoutFor<StarknetStorageValue>>(
9291044
storage: &mut impl ReadOnlyStorage,

0 commit comments

Comments
 (0)