@@ -34,10 +34,15 @@ use starknet_types_core::felt::Felt;
3434use crate :: abi:: constants:: { self } ;
3535use crate :: execution:: entry_point:: { EntryPointExecutionContext , EntryPointTypeAndSelector } ;
3636use crate :: execution:: errors:: PreExecutionError ;
37- use crate :: execution:: execution_utils:: { poseidon_hash_many_cost, sn_api_to_cairo_vm_program} ;
37+ use crate :: execution:: execution_utils:: {
38+ cost_of_encode_felt252_data_and_calc_blake_hash,
39+ poseidon_hash_many_cost,
40+ sn_api_to_cairo_vm_program,
41+ } ;
3842#[ cfg( feature = "cairo_native" ) ]
3943use crate :: execution:: native:: contract_class:: NativeCompiledClassV1 ;
4044use crate :: transaction:: errors:: TransactionExecutionError ;
45+ use crate :: utils:: add_gas;
4146
4247#[ cfg( test) ]
4348#[ path = "contract_class_test.rs" ]
@@ -287,7 +292,7 @@ impl CompiledClassV1 {
287292 /// This is an empiric measurement of several bytecode lengths, which constitutes as the
288293 /// dominant factor in it.
289294 fn estimate_casm_hash_computation_resources ( & self ) -> ExecutionResources {
290- estimate_casm_hash_computation_resources ( & self . bytecode_segment_lengths )
295+ estimate_casm_poseidon_hash_computation_resources ( & self . bytecode_segment_lengths )
291296 }
292297
293298 /// Estimate the VM gas required to perform a CompiledClassHash migration,
@@ -321,7 +326,7 @@ impl CompiledClassV1 {
321326///
322327/// Note: the function focuses on the bytecode size, and currently ignores the cost handling the
323328/// class entry points.
324- pub fn estimate_casm_hash_computation_resources (
329+ pub fn estimate_casm_poseidon_hash_computation_resources (
325330 bytecode_segment_lengths : & NestedIntList ,
326331) -> ExecutionResources {
327332 // The constants in this function were computed by running the Casm code on a few values
@@ -361,6 +366,79 @@ pub fn estimate_casm_hash_computation_resources(
361366 }
362367}
363368
369+ /// Cost to hash a single flat segment of `len` felts.
370+ fn leaf_cost < F > ( len : usize , resources_to_gas_fn : F ) -> GasAmount
371+ where
372+ F : Fn ( & ExecutionResources ) -> GasAmount ,
373+ {
374+ // All `len` inputs treated as “big” felts; no small-felt optimization here.
375+ cost_of_encode_felt252_data_and_calc_blake_hash ( len, 0 , resources_to_gas_fn)
376+ }
377+
378+ /// Cost to hash a multi-segment contract:
379+ fn node_cost < F > ( segs : & [ NestedIntList ] , resources_to_gas_fn : F ) -> GasAmount
380+ where
381+ F : Fn ( & ExecutionResources ) -> GasAmount ,
382+ {
383+ // TODO(AvivG): Add base estimation for node.
384+ let mut gas = GasAmount :: ZERO ;
385+
386+ // TODO(AvivG): Add base estimation of each segment. Could this be part of 'leaf_cost'?
387+ let segment_overhead = GasAmount :: ZERO ;
388+
389+ // 2) For each segment, hash its felts.
390+ for seg in segs {
391+ match seg {
392+ NestedIntList :: Leaf ( len) => {
393+ add_gas ( & mut gas, segment_overhead) ;
394+ add_gas ( & mut gas, leaf_cost ( * len, & resources_to_gas_fn) ) ;
395+ }
396+ _ => panic ! ( "Estimating hash cost only supports at most one level of segmentation." ) ,
397+ }
398+ }
399+
400+ // Node‐level hash over (hash1, len1, hash2, len2, …): one segment hash (“big” felt))
401+ // and one segment length (“small” felt) per segment.
402+ let node_hash_cost = cost_of_encode_felt252_data_and_calc_blake_hash (
403+ segs. len ( ) ,
404+ segs. len ( ) ,
405+ resources_to_gas_fn,
406+ ) ;
407+
408+ add_gas ( & mut gas, node_hash_cost) ;
409+
410+ gas
411+ }
412+
413+ /// Estimates the VM resources to compute the CASM Blake hash for a Cairo-1 contract:
414+ /// - Uses only bytecode size (treats all felts as “big”, ignores the small-felt optimization).
415+ pub fn estimate_casm_blake_hash_computation_resources < F > (
416+ bytecode_segment_lengths : & NestedIntList ,
417+ resources_to_gas_fn : F ,
418+ ) -> GasAmount
419+ where
420+ F : Fn ( & ExecutionResources ) -> GasAmount ,
421+ {
422+ // TODO(AvivG): Currently ignores entry-point costs.
423+
424+ // Basic frame overhead
425+ let resources = ExecutionResources {
426+ n_steps : 0 ,
427+ n_memory_holes : 0 ,
428+ builtin_instance_counter : HashMap :: from ( [ ( BuiltinName :: range_check, 3 ) ] ) ,
429+ } ;
430+ let mut gas = resources_to_gas_fn ( & resources) ;
431+
432+ // Add leaf vs node cost
433+ match bytecode_segment_lengths {
434+ // Single-segment contract (e.g., older Sierra contracts).
435+ NestedIntList :: Leaf ( len) => add_gas ( & mut gas, leaf_cost ( * len, & resources_to_gas_fn) ) ,
436+ NestedIntList :: Node ( segs) => add_gas ( & mut gas, node_cost ( segs, resources_to_gas_fn) ) ,
437+ } ;
438+
439+ gas
440+ }
441+
364442// Returns the set of segments that were visited according to the given visited PCs and segment
365443// lengths.
366444// Each visited segment must have its starting PC visited, and is represented by it.
0 commit comments