@@ -172,7 +172,7 @@ pub trait EstimateCasmHashResources {
172
172
173
173
// TODO(AvivG): Remove allow once used.
174
174
#[ allow( unused) ]
175
- struct CasmV1HashResourceEstimate { }
175
+ pub ( crate ) struct CasmV1HashResourceEstimate { }
176
176
177
177
impl EstimateCasmHashResources for CasmV1HashResourceEstimate {
178
178
fn hash_version ( & self ) -> HashVersion {
@@ -211,7 +211,8 @@ impl EstimateCasmHashResources for CasmV2HashResourceEstimate {
211
211
fn estimated_resources_of_hash_function (
212
212
felt_size_groups : & FeltSizeCount ,
213
213
) -> 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) ;
215
216
let builtin_instance_counter = match felt_size_groups. n_felts ( ) {
216
217
// The empty case does not use builtins at all.
217
218
0 => HashMap :: new ( ) ,
@@ -231,7 +232,6 @@ impl EstimateCasmHashResources for CasmV2HashResourceEstimate {
231
232
}
232
233
}
233
234
}
234
-
235
235
// Constants used for estimating the cost of BLAKE hashing inside Starknet OS.
236
236
// These values are based on empirical measurement by running
237
237
// `encode_felt252_data_and_calc_blake_hash` on various combinations of big and small felts.
@@ -253,71 +253,60 @@ mod blake_estimation {
253
253
pub const STEPS_EMPTY_INPUT : usize = 170 ;
254
254
}
255
255
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
+ }
267
267
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
+ } ;
277
278
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
288
282
}
289
283
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
+ }
323
312
}
0 commit comments