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