Skip to content

Commit

Permalink
Treating all gas-vars as provided 0 if gas is disabled. (#6688)
Browse files Browse the repository at this point in the history
  • Loading branch information
orizi authored Nov 21, 2024
1 parent 86b1639 commit 1d9c664
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 69 deletions.
52 changes: 25 additions & 27 deletions crates/cairo-lang-sierra-gas/src/core_libfunc_cost.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,37 +19,39 @@ struct Ops<'a> {
idx: StatementIdx,
}
impl CostOperations for Ops<'_> {
type CostType = Option<OrderedHashMap<CostTokenType, i64>>;
type CostType = OrderedHashMap<CostTokenType, i64>;

fn cost_token(&self, value: i32, token_type: CostTokenType) -> Self::CostType {
Some(OrderedHashMap::from_iter([(token_type, value as i64)]))
OrderedHashMap::from_iter([(token_type, value as i64)])
}

fn function_token_cost(
&mut self,
function: &cairo_lang_sierra::program::Function,
token_type: CostTokenType,
) -> Self::CostType {
let function_cost = self.gas_info.function_costs.get(&function.id)?;
Some(OrderedHashMap::from_iter([(
token_type,
function_cost.get(&token_type).copied().unwrap_or_default(),
)]))
if let Some(function_cost) = self.gas_info.function_costs.get(&function.id) {
if let Some(v) = function_cost.get(&token_type) {
return OrderedHashMap::from_iter([(token_type, *v)]);
}
}
OrderedHashMap::default()
}

fn statement_var_cost(&self, token_type: CostTokenType) -> Self::CostType {
Some(OrderedHashMap::from_iter([(
token_type,
*self.gas_info.variable_values.get(&(self.idx, token_type))?,
)]))
if let Some(v) = self.gas_info.variable_values.get(&(self.idx, token_type)) {
OrderedHashMap::from_iter([(token_type, *v)])
} else {
OrderedHashMap::default()
}
}

fn add(&self, lhs: Self::CostType, rhs: Self::CostType) -> Self::CostType {
Some(add_maps(lhs?, rhs?))
add_maps(lhs, rhs)
}

fn sub(&self, lhs: Self::CostType, rhs: Self::CostType) -> Self::CostType {
Some(sub_maps(lhs?, rhs?))
sub_maps(lhs, rhs)
}
}

Expand All @@ -60,24 +62,20 @@ pub fn core_libfunc_cost<InfoProvider: InvocationCostInfoProvider>(
idx: &StatementIdx,
libfunc: &CoreConcreteLibfunc,
info_provider: &InfoProvider,
) -> Vec<Option<OrderedHashMap<CostTokenType, i64>>> {
) -> Vec<OrderedHashMap<CostTokenType, i64>> {
let precost = core_libfunc_precost(&mut Ops { gas_info, idx: *idx }, libfunc, info_provider);
let postcost = core_libfunc_postcost(&mut Ops { gas_info, idx: *idx }, libfunc, info_provider);
zip_eq(precost, postcost)
.map(|(precost, postcost)| {
let precost = precost?;
let postcost = postcost?;
Some(
CostTokenType::iter_casm_tokens()
.map(|token| {
(
*token,
precost.get(token).copied().unwrap_or_default()
+ postcost.get(token).copied().unwrap_or_default(),
)
})
.collect(),
)
CostTokenType::iter_casm_tokens()
.map(|token| {
(
*token,
precost.get(token).copied().unwrap_or_default()
+ postcost.get(token).copied().unwrap_or_default(),
)
})
.collect()
})
.collect()
}
57 changes: 25 additions & 32 deletions crates/cairo-lang-sierra-to-casm/src/invocations/gas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ use cairo_lang_casm::casm_build_extend;
use cairo_lang_casm::cell_expression::{CellExpression, CellOperator};
use cairo_lang_casm::operand::{CellRef, DerefOrImmediate, Register};
use cairo_lang_sierra::extensions::gas::{CostTokenType, GasConcreteLibfunc};
use cairo_lang_sierra::program::StatementIdx;
use cairo_lang_sierra_gas::core_libfunc_cost::InvocationCostInfoProvider;
use cairo_lang_utils::casts::IntoOrPanic;
use cairo_lang_utils::ordered_hash_map::OrderedHashMap;
use num_bigint::BigInt;

use super::misc::get_pointer_after_program_code;
use super::{CompiledInvocation, CompiledInvocationBuilder, InvocationError, misc};
use crate::environment::gas_wallet::GasWallet;
use crate::invocations::{
BuiltinInfo, CostValidationInfo, add_input_variables, get_non_fallthrough_statement_id,
};
Expand Down Expand Up @@ -40,11 +40,10 @@ fn build_withdraw_gas(
buffer(1) range_check;
deref gas_counter;
};
let variable_values = &builder.program_info.metadata.gas_info.variable_values;
validate_all_casm_token_vars_available(variable_values, builder.idx)?;
builder.validate_token_vars_availability()?;

// Check if we need to fetch the builtin cost table.
if CostTokenType::iter_precost().any(|token| variable_values[&(builder.idx, *token)] > 0) {
if CostTokenType::iter_precost().any(|token| builder.token_usages(*token) > 0) {
let (pre_instructions, cost_builtin_ptr) =
add_cost_builtin_ptr_fetch_code(&mut casm_builder);
casm_build_extend!(casm_builder, tempvar cost_builtin = cost_builtin_ptr;);
Expand All @@ -55,10 +54,7 @@ fn build_withdraw_gas(
pre_instructions,
);
}
let requested_count: i64 = variable_values
.get(&(builder.idx, CostTokenType::Const))
.copied()
.ok_or(InvocationError::UnknownVariableData)?;
let requested_count = builder.token_usages(CostTokenType::Const);

casm_build_extend! {casm_builder,
let orig_range_check = range_check;
Expand Down Expand Up @@ -91,7 +87,7 @@ fn build_withdraw_gas(
start: orig_range_check,
end: range_check,
}],
extra_costs: Some([-requested_count as i32, 0]),
extra_costs: Some([-requested_count.into_or_panic::<i32>(), 0]),
},
))
}
Expand All @@ -101,11 +97,10 @@ fn build_redeposit_gas(
builder: CompiledInvocationBuilder<'_>,
) -> Result<CompiledInvocation, InvocationError> {
let [gas_counter] = builder.try_get_single_cells()?;
let variable_values = &builder.program_info.metadata.gas_info.variable_values;
validate_all_casm_token_vars_available(variable_values, builder.idx)?;
let requested_count: i64 = variable_values[&(builder.idx, CostTokenType::Const)];
builder.validate_token_vars_availability()?;
let requested_count = builder.token_usages(CostTokenType::Const);
// Check if we need to fetch the builtin cost table.
if CostTokenType::iter_precost().all(|token| variable_values[&(builder.idx, *token)] == 0) {
if CostTokenType::iter_precost().all(|token| builder.token_usages(*token) == 0) {
let gas_counter_value =
gas_counter.to_deref().ok_or(InvocationError::InvalidReferenceExpressionForArgument)?;

Expand Down Expand Up @@ -156,10 +151,7 @@ fn build_builtin_withdraw_gas(
deref gas_counter;
deref builtin_cost;
};
validate_all_casm_token_vars_available(
&builder.program_info.metadata.gas_info.variable_values,
builder.idx,
)?;
builder.validate_token_vars_availability()?;
build_withdraw_gas_given_cost_table(
builder,
casm_builder,
Expand Down Expand Up @@ -209,7 +201,7 @@ fn build_withdraw_gas_given_cost_table(
start: orig_range_check,
end: range_check,
}],
extra_costs: Some([-requested_count as i32, 0]),
extra_costs: Some([-requested_count.into_or_panic::<i32>(), 0]),
},
pre_instructions,
))
Expand All @@ -222,13 +214,12 @@ fn add_get_total_requested_count_code(
builder: &CompiledInvocationBuilder<'_>,
casm_builder: &mut CasmBuilder,
builtin_cost: Var,
) -> Result<(i64, Var), InvocationError> {
let variable_values = &builder.program_info.metadata.gas_info.variable_values;
let const_requested_count: i64 = variable_values[&(builder.idx, CostTokenType::Const)];
) -> Result<(usize, Var), InvocationError> {
let const_requested_count = builder.token_usages(CostTokenType::Const);
let mut total_requested_count =
casm_builder.add_var(CellExpression::Immediate(BigInt::from(const_requested_count)));
for token_type in CostTokenType::iter_precost() {
let token_requested_count = variable_values[&(builder.idx, *token_type)];
let token_requested_count = builder.token_usages(*token_type);
if token_requested_count == 0 {
continue;
}
Expand Down Expand Up @@ -257,17 +248,19 @@ fn add_get_total_requested_count_code(
Ok((const_requested_count, total_requested_count))
}

/// Validates that all the cost token variables are available for statement at `idx`.
fn validate_all_casm_token_vars_available(
variable_values: &OrderedHashMap<(StatementIdx, CostTokenType), i64>,
idx: StatementIdx,
) -> Result<(), InvocationError> {
for token in CostTokenType::iter_casm_tokens() {
if !variable_values.contains_key(&(idx, *token)) {
return Err(InvocationError::UnknownVariableData);
impl CompiledInvocationBuilder<'_> {
/// Validates that all the cost token variables are available for statement at `idx`.
fn validate_token_vars_availability(&self) -> Result<(), InvocationError> {
if !matches!(self.environment.gas_wallet, GasWallet::Disabled) {
for token in CostTokenType::iter_casm_tokens() {
let values = &self.program_info.metadata.gas_info.variable_values;
if !values.contains_key(&(self.idx, *token)) {
return Err(InvocationError::UnknownVariableData);
}
}
}
Ok(())
}
Ok(())
}

/// Handles the get_builtin_costs invocation.
Expand Down
12 changes: 2 additions & 10 deletions crates/cairo-lang-sierra-to-casm/src/invocations/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -463,11 +463,7 @@ impl CompiledInvocationBuilder<'_> {
BranchChanges::new(
ap_change,
ap_tracking_change,
gas_change
.unwrap_or_default()
.iter()
.map(|(token_type, val)| (*token_type, -val))
.collect(),
gas_change.iter().map(|(token_type, val)| (*token_type, -val)).collect(),
expressions,
branch_signature,
&self.environment,
Expand Down Expand Up @@ -522,11 +518,7 @@ impl CompiledInvocationBuilder<'_> {
let gas_changes =
core_libfunc_cost(&self.program_info.metadata.gas_info, &self.idx, self.libfunc, &self)
.into_iter()
.map(|costs| {
costs
.and_then(|costs| costs.get(&CostTokenType::Const).copied())
.unwrap_or_default()
});
.map(|costs| costs.get(&CostTokenType::Const).copied().unwrap_or_default());
let mut final_costs: [ConstCost; BRANCH_COUNT] =
std::array::from_fn(|_| Default::default());
for (cost, (state, _)) in final_costs.iter_mut().zip(branches.iter()) {
Expand Down

0 comments on commit 1d9c664

Please sign in to comment.