Skip to content

Commit 8b873b5

Browse files
starknet_os: os resources test - add keccak
1 parent a215c31 commit 8b873b5

7 files changed

Lines changed: 70 additions & 35 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+
0x050a1cd46f1a35628c7569f85218b7b8b01510cb33834c3bd00885183c5770a5
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 = 175207;
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": "0x4a23be258a6e9666b0f18a523197eabfebbbf869eedeb91a451164a12c1a463",
3+
"virtual_os": "0x50a1cd46f1a35628c7569f85218b7b8b01510cb33834c3bd00885183c5770a5",
44
"aggregator": "0x700786d51b3854af43d8e12180380bda3029be6c1767e007858de6ca2edac40",
55
"aggregator_with_prefix": "0xe08d300e3f5996e43d6d7cc5a20068e0e58cf1309089f2348317ac580f6c1f"
66
}

crates/blockifier/resources/blockifier_versioned_constants_0_14_4.json

Lines changed: 2 additions & 2 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+
"0x50a1cd46f1a35628c7569f85218b7b8b01510cb33834c3bd00885183c5770a5"
133133
],
134134
"constructor_entry_point_selector": "0x28ffe4ff0f226a9107253e17a904099aa4f63a02a5621de0576e5aa71bc5194",
135135
"default_entry_point_selector": "0x0",
@@ -338,7 +338,7 @@
338338
"builtin_instance_counter": {}
339339
},
340340
"KeccakRound": {
341-
"n_steps": 281,
341+
"n_steps": 316,
342342
"n_memory_holes": 0,
343343
"builtin_instance_counter": {
344344
"range_check_builtin": 56,
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
+ /os_constants/allowed_virtual_os_program_hashes/2: "0x6e0e4653c9bf533daba4c89a969a78f082fd2b7ebd38912ca8138441a897bea"
1+
+ /os_constants/allowed_virtual_os_program_hashes/2: "0x50a1cd46f1a35628c7569f85218b7b8b01510cb33834c3bd00885183c5770a5"
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/n_steps: 316
89
~ /os_resources/execute_syscalls/LibraryCall/n_steps: 874
910
~ /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: 231357,
4242
}
4343
"#]]
4444
.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

@@ -97,5 +97,14 @@ mod OsResourcesTestContract {
9797

9898
// get execution info syscall.
9999
get_execution_info_v3_syscall().unwrap_syscall();
100+
101+
// keccak syscall. Second call is to measure the keccak round syscall.
102+
keccak_syscall(array![].span()).unwrap_syscall();
103+
// Exactly 17 input u64s are required to measure a single round.
104+
let mut input = array![];
105+
for _ in 0_u8..17 {
106+
input.append(1_u64);
107+
}
108+
keccak_syscall(input.span()).unwrap_syscall();
100109
}
101110
}

crates/starknet_os_flow_tests/src/os_resources_test.rs

Lines changed: 51 additions & 26 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,
@@ -44,7 +45,7 @@ use crate::test_manager::{
4445
use crate::tests::NON_TRIVIAL_RESOURCE_BOUNDS;
4546

4647
// TODO(Dori): Delete this, or at least reduce it to a minimal set of unmeasurable syscalls.
47-
const UNMEASURABLE_SYSCALLS: [Selector; 28] = [
48+
const UNMEASURABLE_SYSCALLS: [Selector; 26] = [
4849
Selector::DelegateCall,
4950
Selector::DelegateL1Handler,
5051
Selector::GetBlockNumber,
@@ -54,8 +55,6 @@ const UNMEASURABLE_SYSCALLS: [Selector; 28] = [
5455
Selector::GetSequencerAddress,
5556
Selector::GetTxInfo,
5657
Selector::GetTxSignature,
57-
Selector::Keccak,
58-
Selector::KeccakRound,
5958
Selector::Sha256ProcessBlock,
6059
Selector::Sha512ProcessBlock,
6160
Selector::LibraryCallL1Handler,
@@ -90,8 +89,9 @@ const UNMEASURABLE_SYSCALLS: [Selector; 28] = [
9089
/// The second call will always have one more linear element than the first call.
9190
/// Note: Keccak does not store the linear factor in the same entry in the versioned constants, but
9291
/// it does have a measurable linear factor stored under [Selector::KeccakRound].
93-
static SYSCALLS_WITH_LINEAR_FACTOR: LazyLock<HashMap<Selector, usize>> =
94-
LazyLock::new(|| HashMap::from([(Selector::Deploy, 1), (Selector::MetaTxV0, 1)]));
92+
static SYSCALLS_WITH_LINEAR_FACTOR: LazyLock<HashMap<Selector, usize>> = LazyLock::new(|| {
93+
HashMap::from([(Selector::Deploy, 1), (Selector::Keccak, 0), (Selector::MetaTxV0, 1)])
94+
});
9595

9696
/// Expected syscalls in the fee transfer call. Should be removed from the list of syscalls during
9797
/// measurement iteration - only the syscalls called during __execute__ should be measured.
@@ -177,6 +177,9 @@ async fn test_fee_transfer_syscalls() {
177177
#[tokio::test]
178178
async fn test_os_resources_regression() {
179179
let os_resources_contract = FeatureContract::OsResourcesTest(RunnableCairo1::Casm);
180+
let version = StarknetVersion::LATEST;
181+
let mut raw_vc: RawVersionedConstants =
182+
serde_json::from_str(VersionedConstants::json_str(&version).unwrap()).unwrap();
180183

181184
// Setup the test initial state and test builder.
182185
// Need to explicitly set up the state to be able to override the minimal sierra version for gas
@@ -190,6 +193,7 @@ async fn test_os_resources_regression() {
190193
initial_state_data.initial_state.block_context = {
191194
let block_context = &initial_state_data.initial_state.block_context;
192195
let mut vc = block_context.versioned_constants().clone();
196+
assert_eq!(vc, raw_vc.clone().into());
193197
vc.min_sierra_version_for_sierra_gas = SierraVersion::new(99, 99, 99);
194198
BlockContext::new(
195199
block_context.block_info().clone(),
@@ -336,9 +340,7 @@ async fn test_os_resources_regression() {
336340

337341
// If this is a syscall with a linear factor, the next syscall should be an invocation of
338342
// the same syscall with +1 linear element.
339-
let syscall_cost = if let Some(linear_count_in_base) =
340-
SYSCALLS_WITH_LINEAR_FACTOR.get(&selector)
341-
{
343+
if let Some(linear_count_in_base) = SYSCALLS_WITH_LINEAR_FACTOR.get(&selector) {
342344
let next_syscall_trace = syscalls_iter.next().unwrap();
343345
assert_eq!(
344346
selector,
@@ -349,24 +351,50 @@ async fn test_os_resources_regression() {
349351
);
350352
let next_resources =
351353
maybe_deduct_inner(next_syscall_trace.get_resources().unwrap().clone(), selector);
352-
let linear_factor_resources = (&next_resources - &resources).filter_unused_builtins();
353354

354-
// Linear factor is computed; deduct the linear overhead from the base cost to get the
355-
// real base cost.
356-
let constant_resources = (&resources
357-
- &(&linear_factor_resources * *linear_count_in_base))
358-
.filter_unused_builtins();
355+
// Keccak is a special case:
356+
// 1. We store the linear cost as a separate syscall.
357+
// 2. Currently, the Keccak base cost is enforced in the OS to equal the syscall base
358+
// cost (`static_assert KECCAK_GAS_COST == SYSCALL_BASE_GAS_COST`).
359+
// TODO(Dori): If and when (2) is no longer the case, no need to replace `resources`
360+
// (measured keccak base cost) with the syscall base cost, and no need to recompute
361+
// the linear factor.
362+
if selector == Selector::Keccak {
363+
let RawStepGasCost { step_gas_cost: n_steps } =
364+
raw_vc.os_constants.syscall_base_gas_cost.clone();
365+
let constant_resources = ExecutionResources {
366+
n_steps: n_steps.0.try_into().unwrap(),
367+
..Default::default()
368+
};
369+
let linear_factor_resources =
370+
(&next_resources - &constant_resources).filter_unused_builtins();
371+
measurements
372+
.insert(Selector::Keccak, VariableResourceParams::Constant(constant_resources));
373+
measurements.insert(
374+
Selector::KeccakRound,
375+
VariableResourceParams::Constant(linear_factor_resources),
376+
);
377+
} else {
378+
let linear_factor_resources =
379+
(&next_resources - &resources).filter_unused_builtins();
380+
// Linear factor is computed; deduct the linear overhead from the base cost to get
381+
// the real base cost.
382+
let constant_resources = (&resources
383+
- &(&linear_factor_resources * *linear_count_in_base))
384+
.filter_unused_builtins();
359385

360-
VariableResourceParams::WithFactor(ResourcesParams {
361-
constant: constant_resources,
362-
// Syscalls with a linear factor have an unscaled linear factor cost.
363-
calldata_factor: VariableCallDataFactor::Unscaled(linear_factor_resources),
364-
})
386+
measurements.insert(
387+
selector,
388+
VariableResourceParams::WithFactor(ResourcesParams {
389+
constant: constant_resources,
390+
// Syscalls with a linear factor have an unscaled linear factor cost.
391+
calldata_factor: VariableCallDataFactor::Unscaled(linear_factor_resources),
392+
}),
393+
);
394+
}
365395
} else {
366-
VariableResourceParams::Constant(resources)
367-
};
368-
369-
measurements.insert(selector, syscall_cost);
396+
measurements.insert(selector, VariableResourceParams::Constant(resources));
397+
}
370398
}
371399

372400
// Make sure we covered all syscalls we expect to.
@@ -380,9 +408,6 @@ async fn test_os_resources_regression() {
380408
);
381409

382410
// Compare the measurements with the expected values on the latest VC.
383-
let version = StarknetVersion::LATEST;
384-
let mut raw_vc: RawVersionedConstants =
385-
serde_json::from_str(VersionedConstants::json_str(&version).unwrap()).unwrap();
386411
for (syscall, resources) in measurements {
387412
raw_vc.os_resources.execute_syscalls.insert(syscall, resources);
388413
}

0 commit comments

Comments
 (0)