Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Treating all gas-vars as provided 0 if gas is disabled. #6688

Merged
merged 1 commit into from
Nov 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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