Skip to content

Commit 68d0b25

Browse files
blockifier: move logic inside casm_v2hash_resource_estimate
1 parent f12c23e commit 68d0b25

File tree

3 files changed

+68
-78
lines changed

3 files changed

+68
-78
lines changed

crates/blockifier/src/execution/casm_hash_estimation.rs

Lines changed: 54 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ pub trait EstimateCasmHashResources {
173173

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

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

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

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

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

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

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)