@@ -2,6 +2,7 @@ use std::collections::{HashMap, HashSet};
22use std:: sync:: LazyLock ;
33
44use blockifier:: blockifier_versioned_constants:: {
5+ RawStepGasCost ,
56 RawVersionedConstants ,
67 ResourcesParams ,
78 VariableCallDataFactor ,
@@ -45,7 +46,7 @@ use crate::test_manager::{
4546use crate :: tests:: NON_TRIVIAL_RESOURCE_BOUNDS ;
4647
4748// TODO(Dori): Delete this, or at least reduce it to a minimal set of unmeasurable syscalls.
48- const UNMEASURABLE_SYSCALLS : [ Selector ; 28 ] = [
49+ const UNMEASURABLE_SYSCALLS : [ Selector ; 26 ] = [
4950 Selector :: DelegateCall ,
5051 Selector :: DelegateL1Handler ,
5152 Selector :: GetBlockNumber ,
@@ -55,8 +56,6 @@ const UNMEASURABLE_SYSCALLS: [Selector; 28] = [
5556 Selector :: GetSequencerAddress ,
5657 Selector :: GetTxInfo ,
5758 Selector :: GetTxSignature ,
58- Selector :: Keccak ,
59- Selector :: KeccakRound ,
6059 Selector :: Sha256ProcessBlock ,
6160 Selector :: Sha512ProcessBlock ,
6261 Selector :: LibraryCallL1Handler ,
@@ -93,8 +92,9 @@ const UNMEASURABLE_SYSCALLS: [Selector; 28] = [
9392/// `BASE` because the `M1` measurement has a single calldata element (length of calldata: 0).
9493/// Note: Keccak does not store the linear factor in the same entry in the versioned constants, but
9594/// it does have a measurable linear factor stored under [Selector::KeccakRound].
96- static SYSCALLS_WITH_LINEAR_FACTOR : LazyLock < HashMap < Selector , usize > > =
97- LazyLock :: new ( || HashMap :: from ( [ ( Selector :: Deploy , 1 ) , ( Selector :: MetaTxV0 , 1 ) ] ) ) ;
95+ static SYSCALLS_WITH_LINEAR_FACTOR : LazyLock < HashMap < Selector , usize > > = LazyLock :: new ( || {
96+ HashMap :: from ( [ ( Selector :: Deploy , 1 ) , ( Selector :: Keccak , 0 ) , ( Selector :: MetaTxV0 , 1 ) ] )
97+ } ) ;
9898const LARGE_INPUT_LENGTH : usize = 100 ;
9999
100100/// Expected syscalls in the fee transfer call. Should be removed from the list of syscalls during
@@ -181,6 +181,9 @@ async fn test_fee_transfer_syscalls() {
181181#[ tokio:: test]
182182async fn test_os_resources_regression ( ) {
183183 let os_resources_contract = FeatureContract :: OsResourcesTest ( RunnableCairo1 :: Casm ) ;
184+ let version = StarknetVersion :: LATEST ;
185+ let mut raw_vc: RawVersionedConstants =
186+ serde_json:: from_str ( VersionedConstants :: json_str ( & version) . unwrap ( ) ) . unwrap ( ) ;
184187
185188 // Setup the test initial state and test builder.
186189 // Need to explicitly set up the state to be able to override the minimal sierra version for gas
@@ -194,6 +197,7 @@ async fn test_os_resources_regression() {
194197 initial_state_data. initial_state . block_context = {
195198 let block_context = & initial_state_data. initial_state . block_context ;
196199 let mut vc = block_context. versioned_constants ( ) . clone ( ) ;
200+ assert_eq ! ( vc, raw_vc. clone( ) . into( ) ) ;
197201 vc. min_sierra_version_for_sierra_gas = SierraVersion :: new ( 99 , 99 , 99 ) ;
198202 BlockContext :: new (
199203 block_context. block_info ( ) . clone ( ) ,
@@ -340,9 +344,7 @@ async fn test_os_resources_regression() {
340344
341345 // If this is a syscall with a linear factor, the next syscall should be an invocation of
342346 // the same syscall with +1 linear element.
343- let syscall_cost = if let Some ( linear_count_in_base) =
344- SYSCALLS_WITH_LINEAR_FACTOR . get ( & selector)
345- {
347+ if let Some ( linear_count_in_base) = SYSCALLS_WITH_LINEAR_FACTOR . get ( & selector) {
346348 let next_syscall_trace = syscalls_iter. next ( ) . unwrap ( ) ;
347349 assert_eq ! (
348350 selector,
@@ -353,26 +355,52 @@ async fn test_os_resources_regression() {
353355 ) ;
354356 let next_resources =
355357 maybe_deduct_inner ( next_syscall_trace. get_resources ( ) . unwrap ( ) . clone ( ) , selector) ;
356- let linear_factor_resources = ( & next_resources - & resources)
357- . div_ceil ( LARGE_INPUT_LENGTH )
358- . filter_unused_builtins ( ) ;
359358
360- // Linear factor is computed; deduct the linear overhead from the base cost to get the
361- // real base cost.
362- let constant_resources = ( & resources
363- - & ( & linear_factor_resources * * linear_count_in_base) )
364- . filter_unused_builtins ( ) ;
359+ // Keccak is a special case:
360+ // 1. We store the linear cost as a separate syscall.
361+ // 2. Currently, the Keccak base cost is enforced in the OS to equal the syscall base
362+ // cost (`static_assert KECCAK_GAS_COST == SYSCALL_BASE_GAS_COST`).
363+ // TODO(Dori): If and when (2) is no longer the case, no need to replace `resources`
364+ // (measured keccak base cost) with the syscall base cost, and no need to recompute
365+ // the linear factor.
366+ if selector == Selector :: Keccak {
367+ let RawStepGasCost { step_gas_cost : n_steps } =
368+ raw_vc. os_constants . syscall_base_gas_cost . clone ( ) ;
369+ let constant_resources = ExecutionResources {
370+ n_steps : n_steps. 0 . try_into ( ) . unwrap ( ) ,
371+ ..Default :: default ( )
372+ } ;
373+ let linear_factor_resources = ( & next_resources - & constant_resources)
374+ . div_ceil ( LARGE_INPUT_LENGTH )
375+ . filter_unused_builtins ( ) ;
376+ measurements
377+ . insert ( Selector :: Keccak , VariableResourceParams :: Constant ( constant_resources) ) ;
378+ measurements. insert (
379+ Selector :: KeccakRound ,
380+ VariableResourceParams :: Constant ( linear_factor_resources) ,
381+ ) ;
382+ } else {
383+ let linear_factor_resources = ( & next_resources - & resources)
384+ . div_ceil ( LARGE_INPUT_LENGTH )
385+ . filter_unused_builtins ( ) ;
386+ // Linear factor is computed; deduct the linear overhead from the base cost to get
387+ // the real base cost.
388+ let constant_resources = ( & resources
389+ - & ( & linear_factor_resources * * linear_count_in_base) )
390+ . filter_unused_builtins ( ) ;
365391
366- VariableResourceParams :: WithFactor ( ResourcesParams {
367- constant : constant_resources,
368- // Syscalls with a linear factor have an unscaled linear factor cost.
369- calldata_factor : VariableCallDataFactor :: Unscaled ( linear_factor_resources) ,
370- } )
392+ measurements. insert (
393+ selector,
394+ VariableResourceParams :: WithFactor ( ResourcesParams {
395+ constant : constant_resources,
396+ // Syscalls with a linear factor have an unscaled linear factor cost.
397+ calldata_factor : VariableCallDataFactor :: Unscaled ( linear_factor_resources) ,
398+ } ) ,
399+ ) ;
400+ }
371401 } else {
372- VariableResourceParams :: Constant ( resources)
373- } ;
374-
375- measurements. insert ( selector, syscall_cost) ;
402+ measurements. insert ( selector, VariableResourceParams :: Constant ( resources) ) ;
403+ }
376404 }
377405
378406 // Make sure we covered all syscalls we expect to.
@@ -386,9 +414,6 @@ async fn test_os_resources_regression() {
386414 ) ;
387415
388416 // Compare the measurements with the expected values on the latest VC.
389- let version = StarknetVersion :: LATEST ;
390- let mut raw_vc: RawVersionedConstants =
391- serde_json:: from_str ( VersionedConstants :: json_str ( & version) . unwrap ( ) ) . unwrap ( ) ;
392417 for ( syscall, resources) in measurements {
393418 raw_vc. os_resources . execute_syscalls . insert ( syscall, resources) ;
394419 }
0 commit comments