Skip to content

Commit 8aecc8d

Browse files
blockifier: move logic inside casm_v2hash_resource_estimate
1 parent 7568ef4 commit 8aecc8d

File tree

3 files changed

+69
-78
lines changed

3 files changed

+69
-78
lines changed

crates/blockifier/src/execution/casm_hash_estimation.rs

Lines changed: 55 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ pub trait EstimateCasmHashResources {
172172

173173
// TODO(AvivG): Remove allow once used.
174174
#[allow(unused)]
175-
struct CasmV1HashResourceEstimate {}
175+
pub(crate) struct CasmV1HashResourceEstimate {}
176176

177177
impl EstimateCasmHashResources for CasmV1HashResourceEstimate {
178178
fn hash_version(&self) -> HashVersion {
@@ -211,7 +211,8 @@ impl EstimateCasmHashResources for CasmV2HashResourceEstimate {
211211
fn estimated_resources_of_hash_function(
212212
felt_size_groups: &FeltSizeCount,
213213
) -> EstimatedExecutionResources {
214-
let n_steps = estimate_steps_of_encode_felt252_data_and_calc_blake_hash(felt_size_groups);
214+
let n_steps =
215+
Self::estimate_steps_of_encode_felt252_data_and_calc_blake_hash(felt_size_groups);
215216
let builtin_instance_counter = match felt_size_groups.n_felts() {
216217
// The empty case does not use builtins at all.
217218
0 => HashMap::new(),
@@ -231,7 +232,6 @@ impl EstimateCasmHashResources for CasmV2HashResourceEstimate {
231232
}
232233
}
233234
}
234-
235235
// Constants used for estimating the cost of BLAKE hashing inside Starknet OS.
236236
// These values are based on empirical measurement by running
237237
// `encode_felt252_data_and_calc_blake_hash` on various combinations of big and small felts.
@@ -253,71 +253,60 @@ mod blake_estimation {
253253
pub const STEPS_EMPTY_INPUT: usize = 170;
254254
}
255255

256-
fn base_steps_for_blake_hash(n_u32s: usize) -> usize {
257-
let rem_u32s = n_u32s % FeltSizeCount::U32_WORDS_PER_MESSAGE;
258-
if rem_u32s == 0 {
259-
blake_estimation::BASE_STEPS_FULL_MSG
260-
} else {
261-
// This computation is based on running blake2s with different inputs.
262-
// Note: all inputs expand to an even number of u32s --> `rem_u32s` is always even.
263-
blake_estimation::BASE_STEPS_PARTIAL_MSG
264-
+ (rem_u32s / 2) * blake_estimation::STEPS_PER_2_U32_REMINDER
265-
}
266-
}
256+
impl CasmV2HashResourceEstimate {
257+
/// Estimates the total number of VM steps needed to hash the given felts with Blake in the
258+
/// Starknet OS.
259+
fn estimate_steps_of_encode_felt252_data_and_calc_blake_hash(
260+
felt_size_groups: &FeltSizeCount,
261+
) -> usize {
262+
let encoded_u32_len = felt_size_groups.encoded_u32_len();
263+
if encoded_u32_len == 0 {
264+
// The empty input case is a special case.
265+
return blake_estimation::STEPS_EMPTY_INPUT;
266+
}
267267

268-
fn felts_steps(n_big_felts: usize, n_small_felts: usize) -> usize {
269-
let big_steps = n_big_felts
270-
.checked_mul(blake_estimation::STEPS_BIG_FELT)
271-
.expect("Overflow computing big felt steps");
272-
let small_steps = n_small_felts
273-
.checked_mul(blake_estimation::STEPS_SMALL_FELT)
274-
.expect("Overflow computing small felt steps");
275-
big_steps.checked_add(small_steps).expect("Overflow computing total felt steps")
276-
}
268+
// Adds a base cost depending on whether the total fits exactly into full 16-u32 messages.
269+
let base_steps = if encoded_u32_len % FeltSizeCount::U32_WORDS_PER_MESSAGE == 0 {
270+
blake_estimation::BASE_STEPS_FULL_MSG
271+
} else {
272+
// This computation is based on running blake2s with different inputs.
273+
// Note: all inputs expand to an even number of u32s --> `rem_u32s` is always even.
274+
blake_estimation::BASE_STEPS_PARTIAL_MSG
275+
+ (encoded_u32_len % FeltSizeCount::U32_WORDS_PER_MESSAGE / 2)
276+
* blake_estimation::STEPS_PER_2_U32_REMINDER
277+
};
277278

278-
/// Estimates the number of VM steps needed to hash the given felts with Blake in Starknet OS.
279-
/// Each small felt unpacks into 2 u32s, and each big felt into 8 u32s.
280-
/// Adds a base cost depending on whether the total fits exactly into full 16-u32 messages.
281-
fn estimate_steps_of_encode_felt252_data_and_calc_blake_hash(
282-
felt_size_groups: &FeltSizeCount,
283-
) -> usize {
284-
let total_u32s = felt_size_groups.encoded_u32_len();
285-
if total_u32s == 0 {
286-
// The empty input case is a special case.
287-
return blake_estimation::STEPS_EMPTY_INPUT;
279+
base_steps
280+
+ felt_size_groups.large * blake_estimation::STEPS_BIG_FELT
281+
+ felt_size_groups.small * blake_estimation::STEPS_SMALL_FELT
288282
}
289283

290-
let base_steps = base_steps_for_blake_hash(total_u32s);
291-
let felt_steps = felts_steps(felt_size_groups.large, felt_size_groups.small);
292-
293-
base_steps.checked_add(felt_steps).expect("Overflow computing total Blake hash steps")
294-
}
295-
296-
/// Converts the execution resources and blake opcode count to L2 gas.
297-
///
298-
/// Used for both Stwo ("proving_gas") and Stone ("sierra_gas") estimations, which differ in
299-
/// builtin costs. This unified logic is valid because only the `range_check` builtin is used,
300-
/// and its cost is identical across provers (see `bouncer.get_tx_weights`).
301-
// TODO(AvivG): Move inside blake estimation struct.
302-
pub fn blake_execution_resources_estimation_to_gas(
303-
resources: EstimatedExecutionResources,
304-
versioned_constants: &VersionedConstants,
305-
blake_opcode_gas: usize,
306-
) -> GasAmount {
307-
// TODO(AvivG): Remove this once gas computation is separated from resource estimation.
308-
assert!(
309-
resources
310-
.resources()
311-
.builtin_instance_counter
312-
.keys()
313-
.all(|&k| k == BuiltinName::range_check),
314-
"Expected either empty builtins or only `range_check` builtin, got: {:?}. This breaks the \
315-
assumption that builtin costs are identical between provers.",
316-
resources.resources().builtin_instance_counter.keys().collect::<Vec<_>>()
317-
);
318-
319-
resources.to_sierra_gas(
320-
|resources| vm_resources_to_sierra_gas(resources, versioned_constants),
321-
Some(blake_opcode_gas),
322-
)
284+
/// Converts the execution resources and blake opcode count to L2 gas.
285+
///
286+
/// Used for both Stwo ("proving_gas") and Stone ("sierra_gas") estimations, which differ in
287+
/// builtin costs. This unified logic is valid because only the `range_check` builtin is used,
288+
/// and its cost is identical across provers (see `bouncer.get_tx_weights`).
289+
// TODO(AvivG): Move inside blake estimation struct.
290+
pub(crate) fn blake_execution_resources_estimation_to_gas(
291+
resources: EstimatedExecutionResources,
292+
versioned_constants: &VersionedConstants,
293+
blake_opcode_gas: usize,
294+
) -> GasAmount {
295+
// TODO(AvivG): Remove this once gas computation is separated from resource estimation.
296+
assert!(
297+
resources
298+
.resources()
299+
.builtin_instance_counter
300+
.keys()
301+
.all(|&k| k == BuiltinName::range_check),
302+
"Expected either empty builtins or only `range_check` builtin, got: {:?}. This breaks \
303+
the assumption that builtin costs are identical between provers.",
304+
resources.resources().builtin_instance_counter.keys().collect::<Vec<_>>()
305+
);
306+
307+
resources.to_sierra_gas(
308+
|resources| vm_resources_to_sierra_gas(resources, versioned_constants),
309+
Some(blake_opcode_gas),
310+
)
311+
}
323312
}

crates/blockifier/src/execution/casm_hash_estimation_test.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,9 @@ use pretty_assertions::assert_eq;
77
use rstest::rstest;
88
use starknet_types_core::felt::Felt;
99

10-
use crate::execution::casm_hash_estimation::blake_estimation::STEPS_EMPTY_INPUT;
1110
use crate::execution::casm_hash_estimation::{
11+
blake_estimation,
1212
CasmV2HashResourceEstimate,
13-
EstimateCasmHashResources,
14-
estimate_steps_of_encode_felt252_data_and_calc_blake_hash,
1513
EstimatedExecutionResources,
1614
};
1715
use crate::execution::contract_class::FeltSizeCount;
@@ -123,11 +121,15 @@ fn test_u32_constants() {
123121
#[test]
124122
fn test_zero_inputs() {
125123
// logic was written.
126-
let steps = estimate_steps_of_encode_felt252_data_and_calc_blake_hash(&FeltSizeCount {
127-
large: 0,
128-
small: 0,
129-
});
130-
assert_eq!(steps, STEPS_EMPTY_INPUT, "Unexpected base step cost for zero inputs");
124+
let steps =
125+
CasmV2HashResourceEstimate::estimate_steps_of_encode_felt252_data_and_calc_blake_hash(
126+
&FeltSizeCount { large: 0, small: 0 },
127+
);
128+
assert_eq!(
129+
steps,
130+
blake_estimation::STEPS_EMPTY_INPUT,
131+
"Unexpected base step cost for zero inputs"
132+
);
131133

132134
// No opcodes should be emitted.
133135
let opcodes = FeltSizeCount { large: 0, small: 0 }.blake_opcode_count();
@@ -139,7 +141,8 @@ fn test_zero_inputs() {
139141
large: 0,
140142
small: 0,
141143
});
142-
let expected = ExecutionResources { n_steps: STEPS_EMPTY_INPUT, ..Default::default() };
144+
let expected =
145+
ExecutionResources { n_steps: blake_estimation::STEPS_EMPTY_INPUT, ..Default::default() };
143146
assert_eq!(resources.resources(), &expected, "Unexpected resources values for zero-input hash");
144147
assert_eq!(resources.blake_count(), 0, "Expected zero BLAKE opcodes for zero inputs");
145148
}

crates/blockifier/src/execution/contract_class.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ use crate::blockifier_versioned_constants::VersionedConstants;
4343
use crate::bouncer::vm_resources_to_sierra_gas;
4444
use crate::execution::call_info::BuiltinCounterMap;
4545
use crate::execution::casm_hash_estimation::{
46-
blake_execution_resources_estimation_to_gas,
4746
CasmV2HashResourceEstimate,
4847
EstimateCasmHashResources,
4948
};
@@ -596,7 +595,7 @@ fn leaf_cost(
596595
// TODO(AvivG): Call `estimated_resources_of_hash_function` directly, and perform the
597596
// resource→gas conversion only after `estimate_casm_blake_hash_computation_resources`
598597
// executes.
599-
blake_execution_resources_estimation_to_gas(
598+
CasmV2HashResourceEstimate::blake_execution_resources_estimation_to_gas(
600599
CasmV2HashResourceEstimate::estimated_resources_of_hash_function(felt_size_groups),
601600
versioned_constants,
602601
blake_opcode_gas,
@@ -635,7 +634,7 @@ fn node_cost(
635634
// TODO(AvivG): Call `estimated_resources_of_hash_function` directly, and perform the
636635
// resource→gas conversion only after `estimate_casm_blake_hash_computation_resources`
637636
// executes.
638-
let node_hash_cost = blake_execution_resources_estimation_to_gas(
637+
let node_hash_cost = CasmV2HashResourceEstimate::blake_execution_resources_estimation_to_gas(
639638
CasmV2HashResourceEstimate::estimated_resources_of_hash_function(&FeltSizeCount {
640639
large: segs.len(),
641640
small: segs.len(),

0 commit comments

Comments
 (0)