Skip to content

Commit cca3d02

Browse files
starknet_os: os resources test - measure linear factor, add deploy
1 parent 346f65f commit cca3d02

6 files changed

Lines changed: 73 additions & 38 deletions

File tree

crates/apollo_starknet_os_program/src/cairo/starkware/starknet/core/os/constants.cairo

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ const SYSCALL_BASE_GAS_COST = 10000;
108108

109109
// Syscall gas costs.
110110
const CALL_CONTRACT_GAS_COST = 91360;
111-
const DEPLOY_GAS_COST = 147120;
111+
const DEPLOY_GAS_COST = 151970;
112112
const DEPLOY_CALLDATA_FACTOR_GAS_COST = 4850;
113113
const GET_BLOCK_HASH_GAS_COST = 10840;
114114
const GET_CLASS_HASH_AT_GAS_COST = 10000;

crates/apollo_starknet_os_program/src/program_hash.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"os": "0x7b762f60dc1f9ecb199322522749de4e926c1eee33454764ae8974744ef0c5a",
2+
"os": "0x765f8dfbd1ba21a2381a20e92688112bb3633377c11448a2167a230d0b339f0",
33
"virtual_os": "0x28619dbc9767792fb536aaba7a2d55f70faadf808c95ec66b956d33fdee1bc0",
44
"aggregator": "0x700786d51b3854af43d8e12180380bda3029be6c1767e007858de6ca2edac40",
55
"aggregator_with_prefix": "0xe08d300e3f5996e43d6d7cc5a20068e0e58cf1309089f2348317ac580f6c1f"

crates/blockifier/resources/blockifier_versioned_constants_0_14_4.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,11 +247,11 @@
247247
},
248248
"Deploy": {
249249
"constant": {
250-
"n_steps": 1173,
250+
"n_steps": 1181,
251251
"n_memory_holes": 0,
252252
"builtin_instance_counter": {
253253
"range_check_builtin": 21,
254-
"pedersen_builtin": 7
254+
"pedersen_builtin": 8
255255
}
256256
},
257257
"calldata_factor": {
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
+ /os_constants/allowed_virtual_os_program_hashes/2: "0x28619dbc9767792fb536aaba7a2d55f70faadf808c95ec66b956d33fdee1bc0"
22
~ /os_resources/execute_syscalls/CallContract/n_steps: 901
3+
~ /os_resources/execute_syscalls/Deploy/constant/builtin_instance_counter/pedersen_builtin: 8
4+
~ /os_resources/execute_syscalls/Deploy/constant/n_steps: 1183
35
~ /os_resources/execute_syscalls/LibraryCall/n_steps: 874

crates/blockifier_test_utils/resources/feature_contracts/cairo1/os_resources_test_contract.cairo

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#[starknet::contract(account)]
33
mod OsResourcesTestContract {
44
use starknet::info::SyscallResultTrait;
5-
use starknet::syscalls::{call_contract_syscall, library_call_syscall};
5+
use starknet::syscalls::{call_contract_syscall, deploy_syscall, library_call_syscall};
66
use starknet::{ClassHash, ContractAddress};
77

88
const STABLE_EXTERNAL_ENTRY_POINT_SELECTOR: felt252 = selector!("external");
@@ -40,5 +40,13 @@ mod OsResourcesTestContract {
4040
stable_class_hash, STABLE_EXTERNAL_ENTRY_POINT_SELECTOR, array![0].span(),
4141
)
4242
.unwrap_syscall();
43+
44+
// deploy syscall. The resources this syscall consumes can vary depending on the deployed
45+
// contract address, in a non-trivial way (see `normalize_address` in the cairo0 core). For
46+
// this reason we deploy from zero, and choose a specific salt.
47+
// base (no calldata):
48+
deploy_syscall(stable_class_hash, 3, array![0].span(), true).unwrap_syscall();
49+
// linear factor (calldata len = 1):
50+
deploy_syscall(stable_class_hash, 3, array![1, 0].span(), true).unwrap_syscall();
4351
}
4452
}

crates/starknet_os_flow_tests/src/os_resources_test.rs

Lines changed: 58 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ use std::collections::HashSet;
22

33
use 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
3638
use 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

Comments
 (0)