Skip to content

Commit af6b744

Browse files
starknet_os: os resources test - add keccak (#14139)
1 parent 271c314 commit af6b744

8 files changed

Lines changed: 75 additions & 39 deletions

File tree

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ const ALLOWED_VIRTUAL_OS_PROGRAM_HASHES_1 = (
7272
0x06ecb73d21c7d98ddd4148f5bcd91cc2747c65364245fbf32a63b05cca1685c2
7373
);
7474
const ALLOWED_VIRTUAL_OS_PROGRAM_HASHES_2 = (
75-
0x06e0e4653c9bf533daba4c89a969a78f082fd2b7ebd38912ca8138441a897bea
75+
0x0552611434744d19772e04249521f0a3d00d85906c9a600082aaa9339788f8d5
7676
);
7777
const ALLOWED_VIRTUAL_OS_PROGRAM_HASHES_LEN = 3;
7878

@@ -136,7 +136,7 @@ const SECP256R1_MUL_GAS_COST = 13511870;
136136
const SECP256R1_NEW_GAS_COST = 61630;
137137

138138
const KECCAK_GAS_COST = 10000;
139-
const KECCAK_ROUND_COST_GAS_COST = 171707;
139+
const KECCAK_ROUND_COST_GAS_COST = 165137;
140140
const SHA256_PROCESS_BLOCK_GAS_COST = 841295;
141141
const SHA512_PROCESS_BLOCK_GAS_COST = 2413810;
142142

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
2-
"os": "0xb641e53a41bb87cb8f71b6e80fda261c4ab2cde062235cacbe79e2c88564de",
3-
"virtual_os": "0x6e0e4653c9bf533daba4c89a969a78f082fd2b7ebd38912ca8138441a897bea",
2+
"os": "0x30d60f71b7401f270197f0d50658849403bc9d786c2f7b38535cf7f9a389f66",
3+
"virtual_os": "0x552611434744d19772e04249521f0a3d00d85906c9a600082aaa9339788f8d5",
44
"aggregator": "0x700786d51b3854af43d8e12180380bda3029be6c1767e007858de6ca2edac40",
55
"aggregator_with_prefix": "0xe08d300e3f5996e43d6d7cc5a20068e0e58cf1309089f2348317ac580f6c1f"
66
}

crates/blockifier/resources/blockifier_versioned_constants_0_14_4.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@
129129
"allowed_virtual_os_program_hashes": [
130130
"0x3e98c2d7703b03a7edb73ed7f075f97f1dcbaa8f717cdf6e1a57bf058265473",
131131
"0x6ecb73d21c7d98ddd4148f5bcd91cc2747c65364245fbf32a63b05cca1685c2",
132-
"0x6e0e4653c9bf533daba4c89a969a78f082fd2b7ebd38912ca8138441a897bea"
132+
"0x552611434744d19772e04249521f0a3d00d85906c9a600082aaa9339788f8d5"
133133
],
134134
"constructor_entry_point_selector": "0x28ffe4ff0f226a9107253e17a904099aa4f63a02a5621de0576e5aa71bc5194",
135135
"default_entry_point_selector": "0x0",
@@ -338,10 +338,10 @@
338338
"builtin_instance_counter": {}
339339
},
340340
"KeccakRound": {
341-
"n_steps": 281,
341+
"n_steps": 223,
342342
"n_memory_holes": 0,
343343
"builtin_instance_counter": {
344-
"range_check_builtin": 56,
344+
"range_check_builtin": 45,
345345
"keccak_builtin": 1,
346346
"bitwise_builtin": 6
347347
}
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
+ /os_constants/allowed_virtual_os_program_hashes/2: "0x6e0e4653c9bf533daba4c89a969a78f082fd2b7ebd38912ca8138441a897bea"
1+
+ /os_constants/allowed_virtual_os_program_hashes/2: "0x552611434744d19772e04249521f0a3d00d85906c9a600082aaa9339788f8d5"
22
~ /os_resources/execute_syscalls/CallContract/n_steps: 901
33
~ /os_resources/execute_syscalls/EmitEvent/n_steps: 47
44
~ /os_resources/execute_syscalls/GetBlockHash/builtin_instance_counter/range_check_builtin: 3
55
~ /os_resources/execute_syscalls/GetBlockHash/n_steps: 106
66
~ /os_resources/execute_syscalls/GetClassHashAt/n_steps: 75
77
~ /os_resources/execute_syscalls/GetExecutionInfo/n_steps: 111
8+
~ /os_resources/execute_syscalls/KeccakRound/builtin_instance_counter/range_check_builtin: 45
9+
~ /os_resources/execute_syscalls/KeccakRound/n_steps: 223
810
~ /os_resources/execute_syscalls/LibraryCall/n_steps: 874
911
~ /os_resources/execute_syscalls/MetaTxV0/constant/n_steps: 1307

crates/blockifier/src/execution/syscalls/syscall_tests/keccak.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ fn test_keccak(runnable_version: RunnableCairo1) {
3838
l2_to_l1_messages: [],
3939
cairo_native: false,
4040
failed: false,
41-
gas_consumed: 227857,
41+
gas_consumed: 221287,
4242
}
4343
"#]]
4444
.assert_debug_eq(&execution);

crates/blockifier/src/execution/syscalls/syscall_tests/secp.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ fn test_secp256k1(runnable_version: RunnableCairo1) {
3737
l2_to_l1_messages: [],
3838
cairo_native: false,
3939
failed: false,
40-
gas_consumed: 17008279,
40+
gas_consumed: 17001709,
4141
}
4242
"#]];
4343
expectation.assert_debug_eq(&execution);

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ mod OsResourcesTestContract {
44
use starknet::info::SyscallResultTrait;
55
use starknet::syscalls::{
66
call_contract_syscall, deploy_syscall, emit_event_syscall, get_execution_info_v3_syscall,
7-
library_call_syscall,
7+
keccak_syscall, library_call_syscall,
88
};
99
use starknet::{ClassHash, ContractAddress, get_block_hash_syscall, get_class_hash_at_syscall};
1010

@@ -106,5 +106,14 @@ mod OsResourcesTestContract {
106106

107107
// get execution info syscall.
108108
get_execution_info_v3_syscall().unwrap_syscall();
109+
110+
// keccak syscall. Second call is to measure the keccak round syscall.
111+
keccak_syscall(array![].span()).unwrap_syscall();
112+
// Exactly 17 input u64s are required to measure a single round.
113+
let mut input = array![];
114+
for _ in 0..(17 * LARGE_INPUT_LENGTH) {
115+
input.append(1_u64);
116+
}
117+
keccak_syscall(input.span()).unwrap_syscall();
109118
}
110119
}

crates/starknet_os_flow_tests/src/os_resources_test.rs

Lines changed: 53 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::collections::{HashMap, HashSet};
22
use std::sync::LazyLock;
33

44
use blockifier::blockifier_versioned_constants::{
5+
RawStepGasCost,
56
RawVersionedConstants,
67
ResourcesParams,
78
VariableCallDataFactor,
@@ -45,7 +46,7 @@ use crate::test_manager::{
4546
use 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+
});
9898
const 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]
182182
async 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

Comments
 (0)