Skip to content

Commit 99054ea

Browse files
feat(blockifier): add fn encode_felt252_data_and_calc_blake_hash_cost
1 parent 6ecf38b commit 99054ea

File tree

2 files changed

+87
-0
lines changed

2 files changed

+87
-0
lines changed

crates/blockifier/src/execution/execution_utils.rs

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,12 @@ use cairo_vm::vm::vm_core::VirtualMachine;
1818
use num_bigint::BigUint;
1919
use starknet_api::core::ClassHash;
2020
use starknet_api::deprecated_contract_class::Program as DeprecatedProgram;
21+
use starknet_api::execution_resources::GasAmount;
2122
use starknet_api::transaction::fields::Calldata;
2223
use starknet_types_core::felt::Felt;
2324

25+
use crate::blockifier_versioned_constants::VersionedConstants;
26+
use crate::bouncer::vm_resources_to_sierra_gas;
2427
use crate::execution::call_info::{CallExecution, CallInfo, Retdata};
2528
use crate::execution::contract_class::{RunnableCompiledClass, TrackedResource};
2629
use crate::execution::entry_point::{
@@ -42,8 +45,10 @@ use crate::execution::native::entry_point_execution as native_entry_point_execut
4245
use crate::execution::stack_trace::{extract_trailing_cairo1_revert_trace, Cairo1RevertHeader};
4346
use crate::execution::syscalls::hint_processor::{ENTRYPOINT_NOT_FOUND_ERROR, OUT_OF_GAS_ERROR};
4447
use crate::execution::{deprecated_entry_point_execution, entry_point_execution};
48+
use crate::fee::resources;
4549
use crate::state::errors::StateError;
4650
use crate::state::state_api::State;
51+
use crate::utils::{add_maps, u64_from_usize};
4752

4853
pub type Args = Vec<CairoArg>;
4954

@@ -364,3 +369,84 @@ pub fn poseidon_hash_many_cost(data_length: usize) -> ExecutionResources {
364369
builtin_instance_counter: HashMap::from([(BuiltinName::poseidon, data_length / 2 + 1)]),
365370
}
366371
}
372+
373+
mod blake_cost {
374+
// U-32 counts
375+
pub const N_U32S_MESSAGE: usize = 16;
376+
pub const N_U32S_BIG_FELT: usize = 8;
377+
pub const N_U32S_SMALL_FELT: usize = 2;
378+
379+
// Steps counts
380+
pub const STEPS_BIG_FELT: usize = 45;
381+
pub const STEPS_SMALL_FELT: usize = 15;
382+
383+
// One-time segment setup cost (full vs partial)
384+
pub const BASE_STEPS_FULL_MSG: usize = 217;
385+
pub const BASE_STEPS_PARTIAL_MSG: usize = 195;
386+
pub const STEPS_PER_2_U32_REMINDER: usize = 3;
387+
388+
// TODO(AvivG): This is a placeholder, add the actual gas cost for the BLAKE opcode
389+
pub const BLAKE_OPCODE_GAS: usize = 0;
390+
}
391+
392+
/// Estimates the number of VM steps needed to hash the given felts with Blake in Starknet OS.
393+
/// Each small felt unpacks into 2 u32s, and each big felt into 8 u32s.
394+
/// Adds a base cost depending on whether the total fits exactly into full 16-u32 messages.
395+
fn compute_blake_hash_steps(n_big_felts: usize, n_small_felts: usize) -> usize {
396+
let total_u32s =
397+
n_big_felts * blake_cost::N_U32S_BIG_FELT + n_small_felts * blake_cost::N_U32S_SMALL_FELT;
398+
let rem_u32s = total_u32s % blake_cost::N_U32S_MESSAGE;
399+
400+
let base_steps = if rem_u32s == 0 {
401+
blake_cost::BASE_STEPS_FULL_MSG
402+
} else {
403+
blake_cost::BASE_STEPS_PARTIAL_MSG + blake_cost::STEPS_PER_2_U32_REMINDER * (rem_u32s / 2)
404+
};
405+
406+
n_big_felts * blake_cost::STEPS_BIG_FELT
407+
+ n_small_felts * blake_cost::STEPS_SMALL_FELT
408+
+ base_steps
409+
}
410+
411+
/// Returns the number of BLAKE opcodes needed to hash the given felts.
412+
/// Each BLAKE opcode processes 16 u32s (partial messages are padded).
413+
fn count_blake_opcode(n_big_felts: usize, n_small_felts: usize) -> usize {
414+
// Count the total number of u32s to be hashed.
415+
let total_u32s =
416+
n_big_felts * blake_cost::N_U32S_BIG_FELT + n_small_felts * blake_cost::N_U32S_SMALL_FELT;
417+
418+
let full_msgs = total_u32s / blake_cost::N_U32S_MESSAGE;
419+
let has_partial = total_u32s % blake_cost::N_U32S_MESSAGE != 0;
420+
421+
if has_partial { full_msgs + 1 } else { full_msgs }
422+
}
423+
424+
/// Estimates the VM resources for `encode_felt252_data_and_calc_blake_hash` in the Starknet OS.
425+
/// Assumes small felts unpack into 2 u32s and big felts into 8 u32s.
426+
pub fn cost_of_encode_felt252_data_and_calc_blake_hash<F>(
427+
n_big_felts: usize,
428+
n_small_felts: usize,
429+
resources_to_gas_fn: F,
430+
) -> GasAmount
431+
where
432+
F: Fn(&ExecutionResources) -> GasAmount,
433+
{
434+
let n_steps = compute_blake_hash_steps(n_big_felts, n_small_felts);
435+
let n_felts = n_big_felts + n_small_felts;
436+
// One `range_check` per input felt to validate its size.
437+
let builtins = HashMap::from([(BuiltinName::range_check, n_felts)]);
438+
let resources =
439+
ExecutionResources { n_steps, n_memory_holes: 0, builtin_instance_counter: builtins };
440+
let resources_gas = resources_to_gas_fn(&resources);
441+
442+
let blake_op_count = count_blake_opcode(n_big_felts, n_small_felts);
443+
let blake_op_gas = blake_op_count
444+
.checked_mul(blake_cost::BLAKE_OPCODE_GAS)
445+
.map(u64_from_usize)
446+
.map(GasAmount)
447+
.expect("Overflow computing Blake opcode gas.");
448+
449+
resources_gas
450+
.checked_add(blake_op_gas)
451+
.expect("Overflow adding Blake opcode gas to VM resource gas.")
452+
}

crates/blockifier/src/utils.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::collections::HashMap;
22

33
use cairo_vm::vm::runners::cairo_runner::ExecutionResources;
4+
use starknet_api::execution_resources::GasAmount;
45

56
use crate::blockifier_versioned_constants::{BaseGasCosts, BuiltinGasCosts};
67
use crate::transaction::errors::NumericConversionError;

0 commit comments

Comments
 (0)