Skip to content

Commit c356483

Browse files
starknet_os: check estimation vs actual blake count (#9793)
1 parent 3e7abf4 commit c356483

File tree

1 file changed

+53
-7
lines changed

1 file changed

+53
-7
lines changed

crates/starknet_os/src/hints/hint_implementation/compiled_class/compiled_class_test.rs

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use starknet_types_core::felt::Felt;
2929

3030
use crate::hints::hint_implementation::compiled_class::utils::create_bytecode_segment_structure;
3131
use crate::hints::vars::Const;
32+
use crate::opcode_instances::{get_opcode_instances, OpcodeInstanceCounts};
3233
use crate::test_utils::cairo_runner::{
3334
initialize_cairo_runner,
3435
run_cairo_0_entrypoint,
@@ -68,6 +69,7 @@ const EXPECTED_BUILTIN_USAGE_PARTIAL_CONTRACT_V2_HASH: expect_test::Expect =
6869
const EXPECTED_N_STEPS_PARTIAL_CONTRACT_V2_HASH: Expect = expect!["41697"];
6970
// Allowed margin between estimated and actual execution resources.
7071
const ALLOWED_MARGIN_BLAKE_N_STEPS: usize = 267;
72+
const ALLOWED_MARGIN_BLAKE_OPCODE_COUNT: usize = 4;
7173

7274
/// Specifies the expected inputs and outputs for testing a class hash version.
7375
/// Includes entrypoint, bytecode, and expected runtime behavior.
@@ -88,12 +90,20 @@ trait HashVersionTestSpec {
8890
fn expected_hash(&self) -> Expect;
8991
/// The allowed margin for the number of steps.
9092
fn allowed_margin_n_steps(&self) -> usize;
93+
/// The allowed margin for the number of Blake opcodes.
94+
fn allowed_margin_blake_opcode_count(&self) -> usize;
9195
/// Estimates the execution resources for the compiled class hash function.
9296
fn estimate_execution_resources(
9397
&self,
9498
bytecode_segment_felt_sizes: &NestedFeltCounts,
9599
entry_points_by_type: &EntryPointsByType<EntryPointV1>,
96100
) -> ExecutionResources;
101+
/// Estimates the number of Blake opcodes used for the compiled class hash function.
102+
fn estimated_blake_opcode_count(
103+
&self,
104+
bytecode_segment_felt_sizes: &NestedFeltCounts,
105+
entry_points_by_type: &EntryPointsByType<EntryPointV1>,
106+
) -> usize;
97107
}
98108

99109
impl HashVersionTestSpec for HashVersion {
@@ -156,6 +166,12 @@ impl HashVersionTestSpec for HashVersion {
156166
HashVersion::V2 => ALLOWED_MARGIN_BLAKE_N_STEPS,
157167
}
158168
}
169+
fn allowed_margin_blake_opcode_count(&self) -> usize {
170+
match self {
171+
HashVersion::V1 => 0,
172+
HashVersion::V2 => ALLOWED_MARGIN_BLAKE_OPCODE_COUNT,
173+
}
174+
}
159175
fn estimate_execution_resources(
160176
&self,
161177
bytecode_segment_felt_sizes: &NestedFeltCounts,
@@ -178,6 +194,22 @@ impl HashVersionTestSpec for HashVersion {
178194
}
179195
}
180196
}
197+
fn estimated_blake_opcode_count(
198+
&self,
199+
bytecode_segment_felt_sizes: &NestedFeltCounts,
200+
entry_points_by_type: &EntryPointsByType<EntryPointV1>,
201+
) -> usize {
202+
match self {
203+
HashVersion::V1 => 0,
204+
HashVersion::V2 => {
205+
CasmV2HashResourceEstimate::estimated_resources_of_compiled_class_hash(
206+
bytecode_segment_felt_sizes,
207+
entry_points_by_type,
208+
)
209+
.blake_count()
210+
}
211+
}
212+
}
181213
}
182214

183215
/// Runs the compiled class hash entry point for the given contract class,
@@ -187,11 +219,11 @@ fn run_compiled_class_hash_entry_point(
187219
contract_class: &CasmContractClass,
188220
load_full_contract: bool,
189221
hash_version: &HashVersion,
190-
) -> (ExecutionResources, Felt) {
222+
) -> (ExecutionResources, OpcodeInstanceCounts, Felt) {
191223
// Set up the entry point runner configuration.
192224
let runner_config = EntryPointRunnerConfig {
193225
layout: LayoutName::all_cairo,
194-
trace_enabled: false,
226+
trace_enabled: true,
195227
verify_secure: false,
196228
proof_mode: false,
197229
add_main_prefix_to_entrypoint: false, // Set to false since we're using full path.
@@ -256,15 +288,15 @@ fn run_compiled_class_hash_entry_point(
256288

257289
// Get the actual execution resources, and compare with expected values.
258290
let actual_execution_resources = runner.get_execution_resources().unwrap();
259-
291+
let opcode_instances = get_opcode_instances(&runner);
260292
// Get the hash result from the explicit return values.
261293
let EndpointArg::Value(ValueArg::Single(MaybeRelocatable::Int(hash_computed_by_cairo))) =
262294
explicit_return_values[0]
263295
else {
264296
panic!("Expected a single felt return value");
265297
};
266298

267-
(actual_execution_resources, hash_computed_by_cairo)
299+
(actual_execution_resources, opcode_instances, hash_computed_by_cairo)
268300
}
269301

270302
#[rstest]
@@ -280,7 +312,7 @@ fn test_compiled_class_hash(
280312
_ => panic!("Expected ContractClass::V1"),
281313
};
282314
// Run the compiled class hash entry point.
283-
let (actual_execution_resources, hash_computed_by_cairo) =
315+
let (actual_execution_resources, _, hash_computed_by_cairo) =
284316
run_compiled_class_hash_entry_point(&contract_class, load_full_contract, &hash_version);
285317

286318
// Format builtin usage statistics for comparison with expected values.
@@ -376,7 +408,7 @@ fn compare_estimated_vs_actual_casm_hash_resources(
376408
hash_version: &HashVersion,
377409
) {
378410
// Run the compiled class hash entry point with full contract loading.
379-
let (actual_execution_resources, _) =
411+
let (actual_execution_resources, actual_opcode_instances, _) =
380412
run_compiled_class_hash_entry_point(&contract_class, true, hash_version);
381413

382414
let bytecode_segments = NestedFeltCounts::new(
@@ -387,7 +419,7 @@ fn compare_estimated_vs_actual_casm_hash_resources(
387419
// Estimate resources.
388420
let execution_resources_estimation = hash_version.estimate_execution_resources(
389421
&bytecode_segments,
390-
&contract_class.entry_points_by_type.into(),
422+
&contract_class.entry_points_by_type.clone().into(),
391423
);
392424

393425
// Compare n_steps.
@@ -406,4 +438,18 @@ fn compare_estimated_vs_actual_casm_hash_resources(
406438
actual_execution_resources.filter_unused_builtins().builtin_instance_counter,
407439
"{contract_name}: Estimated builtins do not match actual builtins"
408440
);
441+
442+
// Compare Blake opcode count.
443+
let estimated_blake_opcode_count = hash_version.estimated_blake_opcode_count(
444+
&bytecode_segments,
445+
&contract_class.entry_points_by_type.into(),
446+
);
447+
let blake_opcode_count_margin =
448+
estimated_blake_opcode_count.abs_diff(actual_opcode_instances.blake_opcode_count);
449+
let allowed_blake_opcode_count_margin = hash_version.allowed_margin_blake_opcode_count();
450+
assert!(
451+
blake_opcode_count_margin <= allowed_blake_opcode_count_margin,
452+
"{contract_name}: Estimated Blake opcode count differs from actual by more than \
453+
{allowed_blake_opcode_count_margin}. Margin: {blake_opcode_count_margin}"
454+
);
409455
}

0 commit comments

Comments
 (0)