cairo_lang_sierra_gas/
objects.rsuse cairo_lang_sierra::extensions::circuit::CircuitInfo;
use cairo_lang_sierra::extensions::gas::{BuiltinCostsType, CostTokenType};
use cairo_lang_sierra::ids::ConcreteTypeId;
use cairo_lang_sierra::program::Function;
use cairo_lang_utils::casts::IntoOrPanic;
use cairo_lang_utils::collection_arithmetics::{add_maps, sub_maps};
use cairo_lang_utils::ordered_hash_map::OrderedHashMap;
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct ConstCost {
pub steps: i32,
pub holes: i32,
pub range_checks: i32,
pub range_checks96: i32,
}
impl ConstCost {
pub const fn cost(&self) -> i32 {
self.steps * 100 + self.holes * 10 + self.range_checks * 70 + self.range_checks96 * 56
}
pub const fn steps(value: i32) -> Self {
Self { steps: value, holes: 0, range_checks: 0, range_checks96: 0 }
}
pub const fn holes(value: i32) -> Self {
Self { holes: value, steps: 0, range_checks: 0, range_checks96: 0 }
}
pub const fn range_checks(value: i32) -> Self {
Self { range_checks: value, steps: 0, holes: 0, range_checks96: 0 }
}
}
impl ConstCost {
pub const fn add(self, rhs: Self) -> Self {
Self {
steps: self.steps + rhs.steps,
holes: self.holes + rhs.holes,
range_checks: self.range_checks + rhs.range_checks,
range_checks96: self.range_checks96 + rhs.range_checks96,
}
}
}
impl std::ops::Add for ConstCost {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
self.add(rhs)
}
}
impl std::ops::Sub for ConstCost {
type Output = Self;
fn sub(self, rhs: Self) -> Self::Output {
Self {
steps: self.steps - rhs.steps,
holes: self.holes - rhs.holes,
range_checks: self.range_checks - rhs.range_checks,
range_checks96: self.range_checks96 - rhs.range_checks96,
}
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct PreCost(pub OrderedHashMap<CostTokenType, i32>);
impl PreCost {
pub fn builtin(token_type: CostTokenType) -> Self {
Self(OrderedHashMap::from_iter([(token_type, 1)]))
}
pub fn n_builtins(token_type: CostTokenType, n: i32) -> Self {
Self(OrderedHashMap::from_iter([(token_type, n)]))
}
}
impl std::ops::Add for PreCost {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
PreCost(add_maps(self.0, rhs.0))
}
}
impl std::ops::Sub for PreCost {
type Output = Self;
fn sub(self, rhs: Self) -> Self::Output {
PreCost(sub_maps(self.0, rhs.0))
}
}
#[derive(Clone, Copy, Debug)]
pub enum BranchCostSign {
Add,
Subtract,
}
#[derive(Clone, Debug)]
pub enum BranchCost {
Regular { const_cost: ConstCost, pre_cost: PreCost },
FunctionCost { const_cost: ConstCost, function: Function, sign: BranchCostSign },
BranchAlign,
WithdrawGas(WithdrawGasBranchInfo),
RedepositGas,
}
#[derive(Clone, Debug)]
pub struct WithdrawGasBranchInfo {
pub success: bool,
pub with_builtin_costs: bool,
}
impl WithdrawGasBranchInfo {
pub fn const_cost<TokenUsages: Fn(CostTokenType) -> usize>(
&self,
token_usages: TokenUsages,
) -> ConstCost {
let cost_computation: i32 =
BuiltinCostsType::cost_computation_steps(self.with_builtin_costs, token_usages)
.into_or_panic();
let mut steps = 3 + cost_computation;
if !self.success {
if self.with_builtin_costs || cost_computation > 0 {
steps += 2;
} else {
steps += 1;
}
};
ConstCost { steps, range_checks: 1, holes: 0, range_checks96: 0 }
}
}
impl From<ConstCost> for BranchCost {
fn from(value: ConstCost) -> Self {
BranchCost::Regular { const_cost: value, pre_cost: PreCost::default() }
}
}
pub trait CostInfoProvider {
fn type_size(&self, ty: &ConcreteTypeId) -> usize;
fn circuit_info(&self, ty: &ConcreteTypeId) -> &CircuitInfo;
}