Skip to content

Commit 1305fdd

Browse files
blockifier: move logic inside casm_v2hash_resource_estimate
1 parent af6faaa commit 1305fdd

File tree

3 files changed

+71
-75
lines changed

3 files changed

+71
-75
lines changed

crates/blockifier/src/execution/casm_hash_estimation.rs

Lines changed: 55 additions & 64 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 = compute_blake_hash_steps(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,69 +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 compute_blake_hash_steps(felt_size_groups: &FeltSizeCount) -> usize {
282-
let total_u32s = felt_size_groups.encoded_u32_len();
283-
if total_u32s == 0 {
284-
// The empty input case is a special case.
285-
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
286282
}
287283

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

crates/blockifier/src/execution/casm_hash_estimation_test.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,8 @@ 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::{
12-
compute_blake_hash_steps,
13-
CasmV2HashResourceEstimate,
14-
EstimateCasmHashResources,
15-
EstimatedExecutionResources,
11+
blake_estimation, CasmV2HashResourceEstimate, EstimateCasmHashResources, EstimatedExecutionResources
1612
};
1713
use crate::execution::contract_class::FeltSizeCount;
1814

@@ -123,8 +119,15 @@ fn test_u32_constants() {
123119
#[test]
124120
fn test_zero_inputs() {
125121
// logic was written.
126-
let steps = compute_blake_hash_steps(&FeltSizeCount { large: 0, small: 0 });
127-
assert_eq!(steps, STEPS_EMPTY_INPUT, "Unexpected base step cost for zero inputs");
122+
let steps =
123+
CasmV2HashResourceEstimate::estimate_steps_of_encode_felt252_data_and_calc_blake_hash(
124+
&FeltSizeCount { large: 0, small: 0 },
125+
);
126+
assert_eq!(
127+
steps,
128+
blake_estimation::STEPS_EMPTY_INPUT,
129+
"Unexpected base step cost for zero inputs"
130+
);
128131

129132
// No opcodes should be emitted.
130133
let opcodes = FeltSizeCount { large: 0, small: 0 }.blake_opcode_count();
@@ -136,7 +139,10 @@ fn test_zero_inputs() {
136139
large: 0,
137140
small: 0,
138141
});
139-
let expected = ExecutionResources { n_steps: STEPS_EMPTY_INPUT, ..Default::default() };
142+
let expected = ExecutionResources {
143+
n_steps: blake_estimation::STEPS_EMPTY_INPUT,
144+
..Default::default()
145+
};
140146
assert_eq!(resources.resources(), &expected, "Unexpected resources values for zero-input hash");
141147
assert_eq!(resources.blake_count(), 0, "Expected zero BLAKE opcodes for zero inputs");
142148
}

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)