@@ -2,6 +2,8 @@ use std::collections::HashSet;
22
33use blockifier:: blockifier_versioned_constants:: {
44 RawVersionedConstants ,
5+ ResourcesParams ,
6+ VariableCallDataFactor ,
57 VariableResourceParams ,
68 VersionedConstants ,
79} ;
@@ -36,10 +38,9 @@ use crate::test_manager::{TestBuilder, TestBuilderConfig, FUNDED_ACCOUNT_ADDRESS
3638use crate :: tests:: NON_TRIVIAL_RESOURCE_BOUNDS ;
3739
3840// TODO(Dori): Delete this, or at least reduce it to a minimal set of unmeasurable syscalls.
39- const UNMEASURABLE_SYSCALLS : [ Selector ; 34 ] = [
41+ const UNMEASURABLE_SYSCALLS : [ Selector ; 33 ] = [
4042 Selector :: DelegateCall ,
4143 Selector :: DelegateL1Handler ,
42- Selector :: Deploy ,
4344 Selector :: EmitEvent ,
4445 Selector :: GetBlockHash ,
4546 Selector :: GetBlockNumber ,
@@ -73,6 +74,8 @@ const UNMEASURABLE_SYSCALLS: [Selector; 34] = [
7374 Selector :: StorageWrite ,
7475] ;
7576
77+ const SYSCALLS_WITH_LINEAR_FACTOR : [ Selector ; 2 ] = [ Selector :: Deploy , Selector :: MetaTxV0 ] ;
78+
7679/// Measure the OS overhead for each syscall, and compare the results with the latest VC.
7780///
7881/// This test relies on the [starknet_os::hint_processor::os_logger::OsLogger] to capture the
@@ -199,41 +202,66 @@ async fn test_os_resources_regression() {
199202 // Measure each syscall overhead. If the syscall incurs an inner call, subtract the inner call
200203 // overhead.
201204 let mut inner_calls_iter = inner_calls. into_iter ( ) ;
202- let mut visited_syscalls = HashSet :: new ( ) ;
203- let measurements: IndexMap < Selector , ExecutionResources > = syscall_traces
205+ let mut syscalls_iter = syscall_traces
204206 . iter ( )
205- . filter_map ( |syscall_trace| {
206- let selector = syscall_trace. get_selector ( ) ;
207- if UNMEASURABLE_SYSCALLS . contains ( & selector) {
208- return None ;
209- }
207+ . filter ( |syscall_trace| !UNMEASURABLE_SYSCALLS . contains ( & syscall_trace. get_selector ( ) ) ) ;
208+ let mut measurements: IndexMap < Selector , VariableResourceParams > = IndexMap :: new ( ) ;
209+ let mut fetch_inner_resources = |selector : Selector | -> ExecutionResources {
210+ if selector. is_calling_syscall ( ) {
211+ // TODO(Dori): Take opcodes (like blake) into account.
212+ inner_calls_iter. next ( ) . unwrap ( ) . resources . vm_resources
213+ } else {
214+ ExecutionResources :: default ( )
215+ }
216+ } ;
217+ while let Some ( syscall_trace) = syscalls_iter. next ( ) {
218+ let selector = syscall_trace. get_selector ( ) ;
210219
211- // Ensure we don't visit the same syscall twice.
212- assert ! (
213- !visited_syscalls. contains( & selector) ,
214- "Syscall {selector:?} was visited twice."
215- ) ;
216- visited_syscalls. insert ( selector) ;
220+ // Ensure we don't visit the same syscall more than once.
221+ assert ! (
222+ measurements. get( & selector) . is_none( ) ,
223+ "Syscall {selector:?} was visited again, unexpectedly."
224+ ) ;
217225
218- // If this syscall incurs an inner call, it should be the next inner call in the
219- // iterator.
220- let inner_overhead = if selector. is_calling_syscall ( ) {
221- // TODO(Dori): Take opcodes (like blake) into account.
222- inner_calls_iter. next ( ) . unwrap ( ) . resources . vm_resources
223- } else {
224- ExecutionResources :: default ( )
225- } ;
226+ // If this syscall incurs an inner call, it should be the next inner call in the
227+ // iterator.
228+ let inner_overhead = fetch_inner_resources ( selector) ;
229+ // The resources measured here are one of two types: constant, or base cost of a syscall
230+ // with a linear factor.
231+ let resources =
232+ ( syscall_trace. get_resources ( ) . unwrap ( ) - & inner_overhead) . filter_unused_builtins ( ) ;
226233
227- Some ( (
234+ // If this if a syscall with a linear factor, the next syscall should be the linear cost.
235+ // Otherwise, this syscall has a constant cost.
236+ let syscall_cost = if SYSCALLS_WITH_LINEAR_FACTOR . contains ( & selector) {
237+ let next_syscall_trace = syscalls_iter. next ( ) . unwrap ( ) ;
238+ assert_eq ! (
228239 selector,
229- ( syscall_trace. get_resources ( ) . unwrap ( ) - & inner_overhead) . filter_unused_builtins ( ) ,
230- ) )
231- } )
232- . collect ( ) ;
240+ next_syscall_trace. get_selector( ) ,
241+ "Expected next syscall to be the same as the current syscall {selector:?}, but \
242+ got {:?}.",
243+ next_syscall_trace. get_selector( )
244+ ) ;
245+ let next_inner_overhead = fetch_inner_resources ( selector) ;
246+ let next_resources = ( next_syscall_trace. get_resources ( ) . unwrap ( )
247+ - & next_inner_overhead)
248+ . filter_unused_builtins ( ) ;
249+ let linear_factor_resources = ( & next_resources - & resources) . filter_unused_builtins ( ) ;
250+ VariableResourceParams :: WithFactor ( ResourcesParams {
251+ constant : resources,
252+ // Syscalls with a linear factor have an unscaled linear factor cost.
253+ calldata_factor : VariableCallDataFactor :: Unscaled ( linear_factor_resources) ,
254+ } )
255+ } else {
256+ VariableResourceParams :: Constant ( resources)
257+ } ;
258+
259+ measurements. insert ( selector, syscall_cost) ;
260+ }
233261
234262 // Make sure we covered all syscalls we expect to.
235263 assert_eq ! (
236- visited_syscalls ,
264+ HashSet :: from_iter ( measurements . keys ( ) . cloned ( ) ) ,
237265 Selector :: iter( )
238266 . collect:: <HashSet <_>>( )
239267 . difference( & UNMEASURABLE_SYSCALLS . iter( ) . cloned( ) . collect:: <HashSet <_>>( ) )
@@ -246,10 +274,7 @@ async fn test_os_resources_regression() {
246274 let mut raw_vc: RawVersionedConstants =
247275 serde_json:: from_str ( VersionedConstants :: json_str ( & version) . unwrap ( ) ) . unwrap ( ) ;
248276 for ( syscall, resources) in measurements {
249- raw_vc
250- . os_resources
251- . execute_syscalls
252- . insert ( syscall, VariableResourceParams :: Constant ( resources) ) ;
277+ raw_vc. os_resources . execute_syscalls . insert ( syscall, resources) ;
253278 }
254279 expect_file ! [ VersionedConstants :: json_path( & version) . unwrap( ) ]
255280 . assert_eq ( & raw_vc. to_string_pretty ( ) ) ;
0 commit comments