@@ -846,7 +846,11 @@ pub fn get_tx_weights<S: StateReader>(
846846 map_class_hash_to_casm_hash_computation_resources ( state_reader, executed_class_hashes) ?;
847847
848848 // Patricia update + transaction resources.
849- let patrticia_update_resources = get_particia_update_resources ( n_visited_storage_entries) ;
849+ let patrticia_update_resources = get_patricia_update_resources (
850+ n_visited_storage_entries,
851+ // TODO(Yoni): consider counting here the global contract tree and the aliases as well.
852+ state_changes_keys. storage_keys . len ( ) ,
853+ ) ;
850854 let vm_resources = & patrticia_update_resources + & tx_resources. computation . total_vm_resources ( ) ;
851855
852856 // Builtin gas costs for stone and for stwo.
@@ -939,12 +943,23 @@ pub fn map_class_hash_to_casm_hash_computation_resources<S: StateReader>(
939943 . collect ( )
940944}
941945
942- /// Returns the estimated Cairo resources for Patricia tree updates, or hash invocations
943- /// (done by the OS), required for accessing (read/write) the given storage entries.
944- // For each tree: n_visited_leaves * log(n_initialized_leaves)
945- // as the height of a Patricia tree with N uniformly distributed leaves is ~log(N),
946- // and number of visited leaves includes reads and writes.
947- pub fn get_particia_update_resources ( n_visited_storage_entries : usize ) -> ExecutionResources {
946+ /// Returns the estimated Cairo resources for Patricia tree updates given the accessed and
947+ /// modified storage entries.
948+ ///
949+ /// Each access (read or write) requires a traversal of the previous tree, and a write access
950+ /// requires an additional traversal of the new tree.
951+ ///
952+ /// Note:
953+ /// 1. n_visited_storage_entries includes both read and write accesses, and may overlap with
954+ /// n_modified_storage_entries (if the first access to a cell was write) and my not (if a
955+ /// cell was read by a previous transaction and is now modified).
956+ /// 2. In practice, the OS performs a multi-update, which is more efficient than performing
957+ /// separate updates. However, we use this conservative estimate for simplicity.
958+ pub fn get_patricia_update_resources (
959+ n_visited_storage_entries : usize ,
960+ n_modified_storage_entries : usize ,
961+ ) -> ExecutionResources {
962+ // The height of a Patricia tree with N uniformly distributed leaves is ~log(N).
948963 const TREE_HEIGHT_UPPER_BOUND : usize = 24 ;
949964 // TODO(Yoni, 1/5/2024): re-estimate this.
950965 const STEPS_IN_TREE_PER_HEIGHT : usize = 16 ;
@@ -959,8 +974,8 @@ pub fn get_particia_update_resources(n_visited_storage_entries: usize) -> Execut
959974 n_memory_holes : 0 ,
960975 } ;
961976
962- // Multiply by 2 since each storage entry is accessed in both the old and new tree .
963- & resources_per_tree_access * ( n_visited_storage_entries * 2 )
977+ // One traversal per access (read or write), and an additional one per write access .
978+ & resources_per_tree_access * ( n_visited_storage_entries + n_modified_storage_entries )
964979}
965980
966981pub fn verify_tx_weights_within_max_capacity < S : StateReader > (
0 commit comments