From f6418274f28c64db2fc4552f4a67649535c00563 Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Tue, 22 Oct 2024 10:39:49 +0200 Subject: [PATCH 01/31] Revert "Revert builtin cost rework (#874)" This reverts commit 355c250f37cf0977ef2776b1aae2cb2e87c9da3d. --- programs/benches/factorial_2M.c | 5 ++ programs/benches/fib_2M.c | 5 ++ programs/benches/logistic_map.c | 5 ++ src/compiler.rs | 28 ++++++- src/error.rs | 3 + src/executor.rs | 69 +++++++++++----- src/executor/aot.rs | 12 +++ src/executor/contract.rs | 79 ++++++++++++++++--- src/executor/jit.rs | 13 +++ src/libfuncs/gas.rs | 135 ++++++++++++++++++++++++++++---- src/metadata/gas.rs | 15 ++-- src/types.rs | 10 ++- src/types/builtin_costs.rs | 8 +- src/utils.rs | 44 +++++++++++ src/values.rs | 4 +- tests/common.rs | 16 ++-- 16 files changed, 381 insertions(+), 70 deletions(-) diff --git a/programs/benches/factorial_2M.c b/programs/benches/factorial_2M.c index 7db0cfcc6..9beefef5f 100644 --- a/programs/benches/factorial_2M.c +++ b/programs/benches/factorial_2M.c @@ -16,6 +16,7 @@ typedef struct factorial_return_values } result; } factorial_return_values_t; +extern uint64_t* builtin_costs; static void run_bench(factorial_return_values_t*, uint64_t) __attribute__((weakref("_mlir_ciface_factorial_2M::factorial_2M::main(f1)"))); @@ -25,6 +26,10 @@ int main() { factorial_return_values_t return_values; + uint64_t BuiltinCosts[7] = {1, 4050, 583, 4085, 491, 230, 604}; + + builtin_costs = &BuiltinCosts[0]; + run_bench(&return_values, 0); assert(return_values.result.discriminant == 0); diff --git a/programs/benches/fib_2M.c b/programs/benches/fib_2M.c index fecb87cb3..72a420a86 100644 --- a/programs/benches/fib_2M.c +++ b/programs/benches/fib_2M.c @@ -16,6 +16,7 @@ typedef struct fib_return_values } result; } fib_return_values_t; +extern uint64_t* builtin_costs; static void run_bench(fib_return_values_t *, uint64_t) __attribute__((weakref("_mlir_ciface_fib_2M::fib_2M::main(f1)"))); @@ -23,6 +24,10 @@ static void run_bench(fib_return_values_t *, uint64_t) int main() { + uint64_t BuiltinCosts[7] = {1, 4050, 583, 4085, 491, 230, 604}; + + builtin_costs = &BuiltinCosts[0]; + fib_return_values_t return_values; run_bench(&return_values, 0); diff --git a/programs/benches/logistic_map.c b/programs/benches/logistic_map.c index 1294dcdbf..483def4c4 100644 --- a/programs/benches/logistic_map.c +++ b/programs/benches/logistic_map.c @@ -16,6 +16,7 @@ typedef struct map_return_values } result; } map_return_values_t; +extern uint64_t* builtin_costs; static void run_bench(map_return_values_t *, uint64_t) __attribute__((weakref("_mlir_ciface_logistic_map::logistic_map::main(f2)"))); @@ -23,6 +24,10 @@ static void run_bench(map_return_values_t *, uint64_t) int main() { + uint64_t BuiltinCosts[7] = {1, 4050, 583, 4085, 491, 230, 604}; + + builtin_costs = &BuiltinCosts[0]; + map_return_values_t return_values; run_bench(&return_values, 0); diff --git a/src/compiler.rs b/src/compiler.rs index f0efa38d4..85c4e2059 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -74,7 +74,7 @@ use melior::{ arith::CmpiPredicate, cf, func, index, llvm::{self, LoadStoreOptions}, - memref, + memref, ods, }, ir::{ attribute::{ @@ -135,6 +135,30 @@ pub fn compile( } } + { + // Add the builtin_costs global. + // We always add it because symbol look up otherwise can panic. + let region = Region::new(); + let location = Location::unknown(context); + let block = region.append_block(Block::new(&[])); + let value = block.append_op_result( + ods::llvm::mlir_zero(context, llvm::r#type::pointer(context, 0), location).into(), + )?; + block.append_operation(melior::dialect::llvm::r#return(Some(value), location)); + + module.body().append_operation( + ods::llvm::mlir_global( + context, + region, + TypeAttribute::new(llvm::r#type::pointer(context, 0)), + StringAttribute::new(context, "builtin_costs"), + Attribute::parse(context, "#llvm.linkage").unwrap(), + location, + ) + .into(), + ); + } + // Sierra programs have the following structure: // 1. Type declarations, one per line. // 2. Libfunc declarations, one per line. @@ -446,7 +470,7 @@ fn compile_func( initial_state, |statement_idx, mut state| { if let Some(gas_metadata) = metadata.get::() { - let gas_cost = gas_metadata.get_gas_cost_for_statement(statement_idx); + let gas_cost = gas_metadata.get_gas_costs_for_statement(statement_idx); metadata.remove::(); metadata.insert(GasCost(gas_cost)); } diff --git a/src/error.rs b/src/error.rs index c58b2fa57..2cc503d07 100644 --- a/src/error.rs +++ b/src/error.rs @@ -69,6 +69,9 @@ pub enum Error { #[error("integer conversion failed")] IntegerConversion, + #[error("missing BuiltinCosts global symbol, should never happen, this is a bug")] + MissingBuiltinCostsSymbol, + #[error(transparent)] IoError(#[from] std::io::Error), diff --git a/src/executor.rs b/src/executor.rs index 13a570ac6..f88e87735 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -10,7 +10,7 @@ use crate::{ execution_result::{BuiltinStats, ExecutionResult}, starknet::{handler::StarknetSyscallHandlerCallbacks, StarknetSyscallHandler}, types::TypeBuilder, - utils::{libc_free, RangeExt}, + utils::{libc_free, BuiltinCosts, RangeExt}, values::Value, }; use bumpalo::Bump; @@ -69,6 +69,7 @@ extern "C" { fn invoke_dynamic( registry: &ProgramRegistry, function_ptr: *const c_void, + builtin_costs_ptr: Option<*mut c_void>, function_signature: &FunctionSignature, args: &[Value], gas: u128, @@ -141,6 +142,15 @@ fn invoke_dynamic( previous_syscall_handler }); + // Order matters, for the libfunc impl + let builtin_costs: [u64; 7] = BuiltinCosts::default().into(); + + if let Some(builtin_costs_ptr) = builtin_costs_ptr { + unsafe { + *builtin_costs_ptr.cast() = builtin_costs.as_ptr(); + } + } + // Generate argument list. let mut iter = args.iter(); for item in function_signature.param_types.iter().filter_map(|type_id| { @@ -166,6 +176,13 @@ fn invoke_dynamic( (syscall_handler as *mut StarknetSyscallHandlerCallbacks<_>) .to_bytes(&mut invoke_data)?; } + CoreTypeConcrete::BuiltinCosts(_) => { + if let Some(builtin_costs_ptr) = builtin_costs_ptr { + builtin_costs_ptr.to_bytes(&mut invoke_data)?; + } else { + (builtin_costs.as_ptr()).to_bytes(&mut invoke_data)?; + } + } type_info if type_info.is_builtin() => 0u64.to_bytes(&mut invoke_data)?, type_info => ValueWithInfoWrapper { value: iter.next().unwrap(), @@ -249,26 +266,38 @@ fn invoke_dynamic( }, _ if type_info.is_builtin() => { if !type_info.is_zst(registry)? { - let value = match &mut return_ptr { - Some(return_ptr) => unsafe { *read_value::(return_ptr) }, - None => ret_registers[0], - } as usize; - - match type_info { - CoreTypeConcrete::Bitwise(_) => builtin_stats.bitwise = value, - CoreTypeConcrete::EcOp(_) => builtin_stats.ec_op = value, - CoreTypeConcrete::RangeCheck(_) => builtin_stats.range_check = value, - CoreTypeConcrete::Pedersen(_) => builtin_stats.pedersen = value, - CoreTypeConcrete::Poseidon(_) => builtin_stats.poseidon = value, - CoreTypeConcrete::SegmentArena(_) => builtin_stats.segment_arena = value, - CoreTypeConcrete::RangeCheck96(_) => builtin_stats.range_check_96 = value, - CoreTypeConcrete::Circuit(CircuitTypeConcrete::AddMod(_)) => { - builtin_stats.circuit_add = value - } - CoreTypeConcrete::Circuit(CircuitTypeConcrete::MulMod(_)) => { - builtin_stats.circuit_mul = value + if let CoreTypeConcrete::BuiltinCosts(_) = type_info { + // todo: should we use this value? + let _value = match &mut return_ptr { + Some(return_ptr) => unsafe { *read_value::<*mut u64>(return_ptr) }, + None => ret_registers[0] as *mut u64, + }; + } else { + let value = match &mut return_ptr { + Some(return_ptr) => unsafe { *read_value::(return_ptr) }, + None => ret_registers[0], + } as usize; + + match type_info { + CoreTypeConcrete::Bitwise(_) => builtin_stats.bitwise = value, + CoreTypeConcrete::EcOp(_) => builtin_stats.ec_op = value, + CoreTypeConcrete::RangeCheck(_) => builtin_stats.range_check = value, + CoreTypeConcrete::Pedersen(_) => builtin_stats.pedersen = value, + CoreTypeConcrete::Poseidon(_) => builtin_stats.poseidon = value, + CoreTypeConcrete::SegmentArena(_) => { + builtin_stats.segment_arena = value + } + CoreTypeConcrete::RangeCheck96(_) => { + builtin_stats.range_check_96 = value + } + CoreTypeConcrete::Circuit(CircuitTypeConcrete::AddMod(_)) => { + builtin_stats.circuit_add = value + } + CoreTypeConcrete::Circuit(CircuitTypeConcrete::MulMod(_)) => { + builtin_stats.circuit_mul = value + } + _ => unreachable!("{type_id:?}"), } - _ => unreachable!("{type_id:?}"), } } } diff --git a/src/executor/aot.rs b/src/executor/aot.rs index cac2122e2..ebaed4c3e 100644 --- a/src/executor/aot.rs +++ b/src/executor/aot.rs @@ -81,6 +81,7 @@ impl AotNativeExecutor { super::invoke_dynamic( &self.registry, self.find_function_ptr(function_id), + self.find_symbol_ptr("builtin_costs"), self.extract_signature(function_id), args, available_gas, @@ -103,6 +104,7 @@ impl AotNativeExecutor { super::invoke_dynamic( &self.registry, self.find_function_ptr(function_id), + self.find_symbol_ptr("builtin_costs"), self.extract_signature(function_id), args, available_gas, @@ -125,6 +127,7 @@ impl AotNativeExecutor { ContractExecutionResult::from_execution_result(super::invoke_dynamic( &self.registry, self.find_function_ptr(function_id), + self.find_symbol_ptr("builtin_costs"), self.extract_signature(function_id), &[Value::Struct { fields: vec![Value::Array( @@ -152,6 +155,15 @@ impl AotNativeExecutor { } } + pub fn find_symbol_ptr(&self, name: &str) -> Option<*mut c_void> { + unsafe { + self.library + .get::<*mut ()>(name.as_bytes()) + .ok() + .map(|x| x.into_raw().into_raw()) + } + } + fn extract_signature(&self, function_id: &FunctionId) -> &FunctionSignature { &self.registry.get_function(function_id).unwrap().signature } diff --git a/src/executor/contract.rs b/src/executor/contract.rs index 14c4130f2..31f9f0b01 100644 --- a/src/executor/contract.rs +++ b/src/executor/contract.rs @@ -34,7 +34,7 @@ use crate::{ arch::AbiArgument, context::NativeContext, - error::Result, + error::{Error, Result}, execution_result::{BuiltinStats, ContractExecutionResult}, executor::invoke_trampoline, module::NativeModule, @@ -42,6 +42,7 @@ use crate::{ types::TypeBuilder, utils::{ decode_error_message, generate_function_name, get_integer_layout, libc_free, libc_malloc, + BuiltinCosts, }, OptLevel, }; @@ -76,16 +77,27 @@ pub struct AotContractExecutor { library: Arc, path: PathBuf, is_temp_path: bool, - entry_points_info: BTreeMap, + contract_info: ContractInfo, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] -struct EntryPointInfo { - builtins: Vec, +pub struct ContractInfo { + pub version: ContractInfoVersion, + pub entry_points: BTreeMap, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] -enum BuiltinType { +pub enum ContractInfoVersion { + Version0, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] +pub struct EntryPointInfo { + pub builtins: Vec, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] +pub enum BuiltinType { Bitwise, EcOp, RangeCheck, @@ -97,6 +109,7 @@ enum BuiltinType { CircuitMul, Gas, System, + BuiltinCosts, } impl AotContractExecutor { @@ -134,6 +147,9 @@ impl AotContractExecutor { CoreTypeConcrete::RangeCheck(_) => builtins.push(BuiltinType::RangeCheck), CoreTypeConcrete::Pedersen(_) => builtins.push(BuiltinType::Pedersen), CoreTypeConcrete::Poseidon(_) => builtins.push(BuiltinType::Poseidon), + CoreTypeConcrete::BuiltinCosts(_) => { + builtins.push(BuiltinType::BuiltinCosts) + } CoreTypeConcrete::SegmentArena(_) => { builtins.push(BuiltinType::SegmentArena) } @@ -172,7 +188,10 @@ impl AotContractExecutor { library: Arc::new(unsafe { Library::new(&library_path)? }), path: library_path, is_temp_path: true, - entry_points_info: infos, + contract_info: ContractInfo { + version: ContractInfoVersion::Version0, + entry_points: infos, + }, }) } @@ -181,9 +200,9 @@ impl AotContractExecutor { let to = to.as_ref(); std::fs::copy(&self.path, to)?; - let info = serde_json::to_string(&self.entry_points_info)?; + let contract_info = serde_json::to_string(&self.contract_info)?; let path = to.with_extension("json"); - std::fs::write(path, info)?; + std::fs::write(path, contract_info)?; self.path = to.to_path_buf(); self.is_temp_path = false; @@ -194,12 +213,12 @@ impl AotContractExecutor { /// Load the executor from an already compiled library with the additional info json file. pub fn load(library_path: &Path) -> Result { let info_str = std::fs::read_to_string(library_path.with_extension("json"))?; - let info: BTreeMap = serde_json::from_str(&info_str)?; + let contract_info: ContractInfo = serde_json::from_str(&info_str)?; Ok(Self { library: Arc::new(unsafe { Library::new(library_path)? }), path: library_path.to_path_buf(), is_temp_path: false, - entry_points_info: info, + contract_info, }) } @@ -209,16 +228,30 @@ impl AotContractExecutor { function_id: &FunctionId, args: &[Felt], gas: Option, + builtin_costs: Option, mut syscall_handler: impl StarknetSyscallHandler, ) -> Result { let arena = Bump::new(); let mut invoke_data = Vec::::new(); let function_ptr = self.find_function_ptr(function_id, true)?; + let builtin_costs_ptr = self + .find_symbol_ptr("builtin_costs") + .ok_or_else(|| Error::MissingBuiltinCostsSymbol)?; + + let builtin_costs = builtin_costs.unwrap_or_default(); + let builtin_costs: [u64; 7] = builtin_costs.into(); + + unsafe { + *builtin_costs_ptr.cast() = builtin_costs.as_ptr(); + } // it can vary from contract to contract thats why we need to store/ load it. // substract 2, which are the gas and syscall builtin - let num_builtins = self.entry_points_info[&function_id.id].builtins.len() - 2; + let num_builtins = self.contract_info.entry_points[&function_id.id] + .builtins + .len() + - 2; // There is always a return ptr because contracts always return more than 1 thing (builtin counters, syscall, enum) let return_ptr = arena.alloc_layout(unsafe { @@ -231,12 +264,15 @@ impl AotContractExecutor { let mut syscall_handler = StarknetSyscallHandlerCallbacks::new(&mut syscall_handler); - for b in &self.entry_points_info[&function_id.id].builtins { + for b in &self.contract_info.entry_points[&function_id.id].builtins { match b { BuiltinType::Gas => { let gas = gas.unwrap_or(0); gas.to_bytes(&mut invoke_data)?; } + BuiltinType::BuiltinCosts => { + builtin_costs_ptr.to_bytes(&mut invoke_data)?; + } BuiltinType::System => { (&mut syscall_handler as *mut StarknetSyscallHandlerCallbacks<_>) .to_bytes(&mut invoke_data)?; @@ -311,7 +347,7 @@ impl AotContractExecutor { let return_ptr = &mut return_ptr.cast(); - for b in &self.entry_points_info[&function_id.id].builtins { + for b in &self.contract_info.entry_points[&function_id.id].builtins { match b { BuiltinType::Gas => { remaining_gas = unsafe { *read_value::(return_ptr) }; @@ -320,6 +356,11 @@ impl AotContractExecutor { let ptr = return_ptr.cast::<*mut ()>(); *return_ptr = unsafe { NonNull::new_unchecked(ptr.as_ptr().add(1)).cast() }; } + BuiltinType::BuiltinCosts => { + let ptr = return_ptr.cast::<*mut ()>(); + *return_ptr = unsafe { NonNull::new_unchecked(ptr.as_ptr().add(1)).cast() }; + // ptr holds the builtin costs, but they dont change, so its of no use, but we read to advance the ptr. + } x => { let value = unsafe { *read_value::(return_ptr) } as usize; @@ -335,6 +376,7 @@ impl AotContractExecutor { BuiltinType::CircuitMul => builtin_stats.circuit_mul = value, BuiltinType::Gas => {} BuiltinType::System => {} + BuiltinType::BuiltinCosts => {} } } } @@ -436,6 +478,15 @@ impl AotContractExecutor { .into_raw() }) } + + pub fn find_symbol_ptr(&self, name: &str) -> Option<*mut c_void> { + unsafe { + self.library + .get::<*mut ()>(name.as_bytes()) + .ok() + .map(|x| x.into_raw().into_raw()) + } + } } impl Drop for AotContractExecutor { @@ -519,6 +570,7 @@ mod tests { entrypoint_function_id, &[2.into()], Some(u64::MAX as u128), + None, &mut StubSyscallHandler::default(), ) .unwrap(); @@ -544,6 +596,7 @@ mod tests { entrypoint_function_id, &[], Some(u64::MAX as u128), + None, &mut StubSyscallHandler::default(), ) .unwrap(); diff --git a/src/executor/jit.rs b/src/executor/jit.rs index 55bfafcbe..4b50ce113 100644 --- a/src/executor/jit.rs +++ b/src/executor/jit.rs @@ -79,6 +79,7 @@ impl<'m> JitNativeExecutor<'m> { super::invoke_dynamic( &self.registry, self.find_function_ptr(function_id), + self.find_symbol_ptr("builtin_costs"), self.extract_signature(function_id).unwrap(), args, available_gas, @@ -102,6 +103,7 @@ impl<'m> JitNativeExecutor<'m> { super::invoke_dynamic( &self.registry, self.find_function_ptr(function_id), + self.find_symbol_ptr("builtin_costs"), self.extract_signature(function_id).unwrap(), args, available_gas, @@ -124,6 +126,7 @@ impl<'m> JitNativeExecutor<'m> { ContractExecutionResult::from_execution_result(super::invoke_dynamic( &self.registry, self.find_function_ptr(function_id), + self.find_symbol_ptr("builtin_costs"), self.extract_signature(function_id).unwrap(), &[Value::Struct { fields: vec![Value::Array( @@ -145,6 +148,16 @@ impl<'m> JitNativeExecutor<'m> { self.engine.lookup(&function_name) as *mut c_void } + pub fn find_symbol_ptr(&self, name: &str) -> Option<*mut c_void> { + let ptr = self.engine.lookup(name) as *mut c_void; + + if ptr.is_null() { + None + } else { + Some(ptr) + } + } + fn extract_signature(&self, function_id: &FunctionId) -> Option<&FunctionSignature> { self.program_registry() .get_function(function_id) diff --git a/src/libfuncs/gas.rs b/src/libfuncs/gas.rs index 474fe7443..b7eabecc9 100644 --- a/src/libfuncs/gas.rs +++ b/src/libfuncs/gas.rs @@ -9,7 +9,7 @@ use crate::{ use cairo_lang_sierra::{ extensions::{ core::{CoreLibfunc, CoreType}, - gas::GasConcreteLibfunc, + gas::{CostTokenType, GasConcreteLibfunc}, lib_func::SignatureOnlyConcreteLibfunc, ConcreteLibfunc, }, @@ -18,9 +18,10 @@ use cairo_lang_sierra::{ use melior::{ dialect::{ arith::{self, CmpiPredicate}, - llvm, ods, + llvm::{self, r#type::pointer}, + ods, }, - ir::{r#type::IntegerType, Block, Location}, + ir::{attribute::FlatSymbolRefAttribute, r#type::IntegerType, Block, Location}, Context, }; @@ -83,22 +84,74 @@ pub fn build_withdraw_gas<'ctx, 'this>( super::increment_builtin_counter(context, entry, location, entry.argument(0)?.into())?; let current_gas = entry.argument(1)?.into(); - let cost = metadata.get::().and_then(|x| x.0); + let gas_cost = metadata + .get::() + .expect("builtin_withdraw_gas should always have a gas cost"); let u128_type: melior::ir::Type = IntegerType::new(context, 128).into(); - let gas_cost_val = - entry.const_int_from_type(context, location, cost.unwrap_or(0), u128_type)?; + let u64_type: melior::ir::Type = IntegerType::new(context, 64).into(); + + // Get the ptr to the global, holding a ptr to the list. + let builtin_ptr_ptr = entry.append_op_result( + ods::llvm::mlir_addressof( + context, + pointer(context, 0), + FlatSymbolRefAttribute::new(context, "builtin_costs"), + location, + ) + .into(), + )?; + + let builtin_ptr = entry.load(context, location, builtin_ptr_ptr, pointer(context, 0))?; + + let mut final_gas_cost = entry.const_int_from_type(context, location, 0, u128_type)?; + + for (cost, token_type) in &gas_cost.0 { + if *cost == 0 { + continue; + } + + let token_type_index = match token_type { + CostTokenType::Const => 0, + CostTokenType::Pedersen => 1, + CostTokenType::Bitwise => 2, + CostTokenType::EcOp => 3, + CostTokenType::Poseidon => 4, + CostTokenType::AddMod => 5, + CostTokenType::MulMod => 6, + _ => unreachable!(), + }; + + let gas_cost_val = entry.const_int_from_type(context, location, *cost, u128_type)?; + let token_type_index_val = + entry.const_int_from_type(context, location, token_type_index, u64_type)?; + + let cost_value_ptr = entry.append_op_result(llvm::get_element_ptr_dynamic( + context, + builtin_ptr, + &[token_type_index_val], + u64_type, + pointer(context, 0), + location, + ))?; + let cost_value = entry.load(context, location, cost_value_ptr, u64_type)?; + let cost_value = entry.append_op_result(arith::extui(cost_value, u128_type, location))?; + let total_gas_cost_val = + entry.append_op_result(arith::muli(gas_cost_val, cost_value, location))?; + final_gas_cost = + entry.append_op_result(arith::addi(final_gas_cost, total_gas_cost_val, location))?; + } let is_enough = entry.append_op_result(arith::cmpi( context, CmpiPredicate::Uge, current_gas, - gas_cost_val, + final_gas_cost, location, ))?; let resulting_gas = entry.append_op_result( - ods::llvm::intr_usub_sat(context, current_gas, gas_cost_val, location).into(), + ods::llvm::intr_usub_sat(context, current_gas, final_gas_cost, location).into(), )?; entry.append_operation(helper.cond_br( @@ -125,23 +178,63 @@ pub fn build_builtin_withdraw_gas<'ctx, 'this>( let range_check = super::increment_builtin_counter(context, entry, location, entry.argument(0)?.into())?; let current_gas = entry.argument(1)?.into(); + let builtin_ptr = entry.argument(2)?.into(); - let cost = metadata.get::().and_then(|x| x.0); + let gas_cost = metadata + .get::() + .expect("builtin_withdraw_gas should always have a gas cost"); let u128_type: melior::ir::Type = IntegerType::new(context, 128).into(); - let gas_cost_val = - entry.const_int_from_type(context, location, cost.unwrap_or(0), u128_type)?; + let u64_type: melior::ir::Type = IntegerType::new(context, 64).into(); + + let mut final_gas_cost = entry.const_int_from_type(context, location, 0, u128_type)?; + + for (cost, token_type) in &gas_cost.0 { + if *cost == 0 { + continue; + } + + let token_type_index = match token_type { + CostTokenType::Const => 0, + CostTokenType::Pedersen => 1, + CostTokenType::Bitwise => 2, + CostTokenType::EcOp => 3, + CostTokenType::Poseidon => 4, + CostTokenType::AddMod => 5, + CostTokenType::MulMod => 6, + _ => unreachable!(), + }; + + let gas_cost_val = entry.const_int_from_type(context, location, *cost, u128_type)?; + let token_type_index_val = + entry.const_int_from_type(context, location, token_type_index, u64_type)?; + + let cost_value_ptr = entry.append_op_result(llvm::get_element_ptr_dynamic( + context, + builtin_ptr, + &[token_type_index_val], + u64_type, + pointer(context, 0), + location, + ))?; + let cost_value = entry.load(context, location, cost_value_ptr, u64_type)?; + let cost_value = entry.append_op_result(arith::extui(cost_value, u128_type, location))?; + let total_gas_cost_val = + entry.append_op_result(arith::muli(gas_cost_val, cost_value, location))?; + final_gas_cost = + entry.append_op_result(arith::addi(final_gas_cost, total_gas_cost_val, location))?; + } let is_enough = entry.append_op_result(arith::cmpi( context, CmpiPredicate::Uge, current_gas, - gas_cost_val, + final_gas_cost, location, ))?; let resulting_gas = entry.append_op_result( - ods::llvm::intr_usub_sat(context, current_gas, gas_cost_val, location).into(), + ods::llvm::intr_usub_sat(context, current_gas, final_gas_cost, location).into(), )?; entry.append_operation(helper.cond_br( @@ -173,10 +266,20 @@ pub fn build_get_builtin_costs<'ctx, 'this>( &info.branch_signatures()[0].vars[0].ty, )?; - // TODO: Implement libfunc. - let op0 = entry.append_op_result(llvm::undef(builtin_costs_ty, location))?; + // Get the ptr to the global, holding a ptr to the list. + let builtin_ptr_ptr = entry.append_op_result( + ods::llvm::mlir_addressof( + context, + pointer(context, 0), + FlatSymbolRefAttribute::new(context, "builtin_costs"), + location, + ) + .into(), + )?; + + let builtin_ptr = entry.load(context, location, builtin_ptr_ptr, builtin_costs_ty)?; - entry.append_operation(helper.br(0, &[op0], location)); + entry.append_operation(helper.br(0, &[builtin_ptr], location)); Ok(()) } diff --git a/src/metadata/gas.rs b/src/metadata/gas.rs index 9378c5895..9bb2ac34b 100644 --- a/src/metadata/gas.rs +++ b/src/metadata/gas.rs @@ -20,8 +20,9 @@ pub struct GasMetadata { pub gas_info: GasInfo, } -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct GasCost(pub Option); +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +// Cost, token type (index into builtin costs). +pub struct GasCost(pub Vec<(u128, CostTokenType)>); /// Configuration for metadata computation. #[derive(Debug, Clone)] @@ -102,16 +103,18 @@ impl GasMetadata { ) } - pub fn get_gas_cost_for_statement(&self, idx: StatementIdx) -> Option { - let mut cost = None; + pub fn get_gas_costs_for_statement(&self, idx: StatementIdx) -> Vec<(u128, CostTokenType)> { + let mut costs = Vec::new(); for cost_type in CostTokenType::iter_casm_tokens() { if let Some(amount) = self.get_gas_cost_for_statement_and_cost_token_type(idx, *cost_type) { - *cost.get_or_insert(0) += amount * token_gas_cost(*cost_type) as u128; + if amount > 0 { + costs.push((amount, *cost_type)); + } } } - cost + costs } pub fn get_gas_cost_for_statement_and_cost_token_type( diff --git a/src/types.rs b/src/types.rs index bf1dbb8bf..6d0d6314e 100644 --- a/src/types.rs +++ b/src/types.rs @@ -549,10 +549,12 @@ impl TypeBuilder for CoreTypeConcrete { | CoreTypeConcrete::Poseidon(_) | CoreTypeConcrete::RangeCheck96(_) | CoreTypeConcrete::SegmentArena(_) => false, + + // A ptr to a list of costs. + CoreTypeConcrete::BuiltinCosts(_) => false, + // Other builtins: - CoreTypeConcrete::BuiltinCosts(_) - | CoreTypeConcrete::Uint128MulGuarantee(_) - | CoreTypeConcrete::Coupon(_) => true, + CoreTypeConcrete::Uint128MulGuarantee(_) | CoreTypeConcrete::Coupon(_) => true, // Normal types: CoreTypeConcrete::Array(_) @@ -634,7 +636,7 @@ impl TypeBuilder for CoreTypeConcrete { CoreTypeConcrete::EcState(_) => layout_repeat(&get_integer_layout(252), 4)?.0, CoreTypeConcrete::Felt252(_) => get_integer_layout(252), CoreTypeConcrete::GasBuiltin(_) => get_integer_layout(128), - CoreTypeConcrete::BuiltinCosts(_) => Layout::new::<()>(), + CoreTypeConcrete::BuiltinCosts(_) => Layout::new::<*const ()>(), CoreTypeConcrete::Uint8(_) => get_integer_layout(8), CoreTypeConcrete::Uint16(_) => get_integer_layout(16), CoreTypeConcrete::Uint32(_) => get_integer_layout(32), diff --git a/src/types/builtin_costs.rs b/src/types/builtin_costs.rs index b7a202dce..7fc2e978c 100644 --- a/src/types/builtin_costs.rs +++ b/src/types/builtin_costs.rs @@ -1,4 +1,7 @@ //! # Builtin costs type +//! +//! A ptr to a list of u64, this list will not change at runtime in size and thus we only really need to store the pointer, +//! it can be allocated on the stack on rust side and passed. use super::WithSelf; use crate::{error::Result, metadata::MetadataStorage}; @@ -11,7 +14,7 @@ use cairo_lang_sierra::{ }; use melior::{ dialect::llvm, - ir::{r#type::IntegerType, Module, Type}, + ir::{Module, Type}, Context, }; @@ -25,5 +28,6 @@ pub fn build<'ctx>( _metadata: &mut MetadataStorage, _info: WithSelf, ) -> Result> { - Ok(llvm::r#type::array(IntegerType::new(context, 8).into(), 0)) + // A ptr to a list of u64 + Ok(llvm::r#type::pointer(context, 0)) } diff --git a/src/utils.rs b/src/utils.rs index 2c5fc73d9..090b03292 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -5,7 +5,9 @@ pub(crate) use self::{ }; use crate::{metadata::MetadataStorage, OptLevel}; use cairo_lang_compiler::CompilerConfig; +use cairo_lang_runner::token_gas_cost; use cairo_lang_sierra::{ + extensions::gas::CostTokenType, ids::FunctionId, program::{GenFunction, Program, StatementIdx}, }; @@ -15,6 +17,7 @@ use melior::{ Context, Error, ExecutionEngine, }; use num_bigint::{BigInt, BigUint, Sign}; +use serde::{Deserialize, Serialize}; use starknet_types_core::felt::Felt; use std::sync::LazyLock; use std::{ @@ -49,6 +52,47 @@ pub static HALF_PRIME: LazyLock = LazyLock::new(|| { .unwrap() }); +#[derive(Debug, Clone, Copy, Deserialize, Serialize)] +pub struct BuiltinCosts { + pub r#const: u64, + pub pedersen: u64, + pub bitwise: u64, + pub ecop: u64, + pub poseidon: u64, + pub add_mod: u64, + pub mul_mod: u64, +} + +impl From for [u64; 7] { + // Order matters, for the libfunc impl + // https://github.com/starkware-libs/sequencer/blob/1b7252f8a30244d39614d7666aa113b81291808e/crates/blockifier/src/execution/entry_point_execution.rs#L208 + fn from(value: BuiltinCosts) -> Self { + [ + value.r#const, + value.pedersen, + value.bitwise, + value.ecop, + value.poseidon, + value.add_mod, + value.mul_mod, + ] + } +} + +impl Default for BuiltinCosts { + fn default() -> Self { + Self { + r#const: token_gas_cost(CostTokenType::Const) as u64, + pedersen: token_gas_cost(CostTokenType::Pedersen) as u64, + bitwise: token_gas_cost(CostTokenType::Bitwise) as u64, + ecop: token_gas_cost(CostTokenType::EcOp) as u64, + poseidon: token_gas_cost(CostTokenType::Poseidon) as u64, + add_mod: token_gas_cost(CostTokenType::AddMod) as u64, + mul_mod: token_gas_cost(CostTokenType::MulMod) as u64, + } + } +} + #[cfg(feature = "with-mem-tracing")] #[allow(unused_imports)] pub(crate) use self::mem_tracing::{ diff --git a/src/values.rs b/src/values.rs index 213360111..796933dec 100644 --- a/src/values.rs +++ b/src/values.rs @@ -1,6 +1,6 @@ -//! # JIT params and return values de/serialization +//! # Params and return values de/serialization //! -//! A Rusty interface to provide parameters to JIT calls. +//! A Rusty interface to provide parameters to cairo-native entry point calls. use crate::{ error::{CompilerError, Error}, diff --git a/tests/common.rs b/tests/common.rs index 649499276..b35a85e18 100644 --- a/tests/common.rs +++ b/tests/common.rs @@ -391,7 +391,6 @@ pub fn run_vm_contract( .collect_vec() } -#[track_caller] pub fn compare_inputless_program(program_path: &str) { let program: (String, Program, SierraCasmRunner) = load_cairo_path(program_path); let program = &program; @@ -438,7 +437,6 @@ pub fn run_native_starknet_contract( /// the results automatically, triggering a proptest assert if there is a mismatch. /// /// Left of report of the assert is the cairo vm result, right side is cairo native -#[track_caller] pub fn compare_outputs( program: &Program, entry_point: &FunctionId, @@ -744,8 +742,12 @@ pub fn compare_outputs( .unwrap_or(false) }); assert_eq!( - vm_result.gas_counter.unwrap_or_else(|| Felt::from(0)), - Felt::from(native_result.remaining_gas.unwrap_or(0)), + vm_result + .gas_counter + .unwrap_or_else(|| Felt::from(0)) + .to_bigint(), + Felt::from(native_result.remaining_gas.unwrap_or(0)).to_bigint(), + "gas mismatch" ); let vm_result = match &vm_result.value { @@ -807,7 +809,11 @@ pub fn compare_outputs( }, }; - pretty_assertions_sorted::assert_eq!(native_result.return_value, vm_result); + pretty_assertions_sorted::assert_eq!( + native_result.return_value, + vm_result, + "return value mismatch" + ); Ok(()) } From 319038ff578b89f0ab131547184d021bcfe1ce3d Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Tue, 22 Oct 2024 11:32:18 +0200 Subject: [PATCH 02/31] x --- src/compiler.rs | 22 +++++++++++++--------- src/executor/contract.rs | 37 +++++++++++++++++++++++++------------ src/libfuncs/gas.rs | 14 +++++++------- 3 files changed, 45 insertions(+), 28 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index 85c4e2059..f5feac842 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -147,15 +147,19 @@ pub fn compile( block.append_operation(melior::dialect::llvm::r#return(Some(value), location)); module.body().append_operation( - ods::llvm::mlir_global( - context, - region, - TypeAttribute::new(llvm::r#type::pointer(context, 0)), - StringAttribute::new(context, "builtin_costs"), - Attribute::parse(context, "#llvm.linkage").unwrap(), - location, - ) - .into(), + { + let op = + ods::llvm::mlir_global( + context, + region, + TypeAttribute::new(llvm::r#type::pointer(context, 0)), + StringAttribute::new(context, "builtin_costs"), + Attribute::parse(context, "#llvm.linkage").unwrap(), + location, + ); + + op.into() + }, ); } diff --git a/src/executor/contract.rs b/src/executor/contract.rs index 31f9f0b01..5b050c432 100644 --- a/src/executor/contract.rs +++ b/src/executor/contract.rs @@ -112,6 +112,25 @@ pub enum BuiltinType { BuiltinCosts, } +impl BuiltinType { + pub fn size_in_bytes(&self) -> usize { + match self { + BuiltinType::Bitwise => 8, + BuiltinType::EcOp => 8, + BuiltinType::RangeCheck => 8, + BuiltinType::SegmentArena => 8, + BuiltinType::Poseidon => 8, + BuiltinType::Pedersen => 8, + BuiltinType::RangeCheck96 => 8, + BuiltinType::CircuitAdd => 8, + BuiltinType::CircuitMul => 8, + BuiltinType::Gas => 16, + BuiltinType::System => 8, + BuiltinType::BuiltinCosts => 8, + } + } +} + impl AotContractExecutor { /// Create the executor from a sierra program with the given optimization level. /// You can save the library on the desired location later using `save`. @@ -247,17 +266,13 @@ impl AotContractExecutor { } // it can vary from contract to contract thats why we need to store/ load it. - // substract 2, which are the gas and syscall builtin - let num_builtins = self.contract_info.entry_points[&function_id.id] - .builtins - .len() - - 2; + let builtins_size: usize = self.contract_info.entry_points[&function_id.id].builtins.iter().map(|x| x.size_in_bytes()).sum(); // There is always a return ptr because contracts always return more than 1 thing (builtin counters, syscall, enum) let return_ptr = arena.alloc_layout(unsafe { - // 64 = size of enum + syscall + u128 from gas builtin + 8 bytes for each additional builtin counter - // align is 16 because of the u128 - Layout::from_size_align_unchecked(64 + 8 * num_builtins, 16) + // 64 = size of enum + builtin sizes + // align is 16 because of the u128 from gas + Layout::from_size_align_unchecked(64 + builtins_size, 16) }); return_ptr.as_ptr().to_bytes(&mut invoke_data)?; @@ -353,12 +368,10 @@ impl AotContractExecutor { remaining_gas = unsafe { *read_value::(return_ptr) }; } BuiltinType::System => { - let ptr = return_ptr.cast::<*mut ()>(); - *return_ptr = unsafe { NonNull::new_unchecked(ptr.as_ptr().add(1)).cast() }; + unsafe { read_value::<*mut ()>(return_ptr) }; } BuiltinType::BuiltinCosts => { - let ptr = return_ptr.cast::<*mut ()>(); - *return_ptr = unsafe { NonNull::new_unchecked(ptr.as_ptr().add(1)).cast() }; + unsafe { read_value::<*mut ()>(return_ptr) }; // ptr holds the builtin costs, but they dont change, so its of no use, but we read to advance the ptr. } x => { diff --git a/src/libfuncs/gas.rs b/src/libfuncs/gas.rs index b7eabecc9..40ddd1138 100644 --- a/src/libfuncs/gas.rs +++ b/src/libfuncs/gas.rs @@ -52,7 +52,7 @@ pub fn build<'ctx, 'this>( } } -/// Generate MLIR operations for the `get_builtin_costs` libfunc. +/// Generate MLIR operations for the `get_available_gas` libfunc. pub fn build_get_available_gas<'ctx, 'this>( _context: &'ctx Context, _registry: &ProgramRegistry, @@ -126,7 +126,7 @@ pub fn build_withdraw_gas<'ctx, 'this>( let token_type_index_val = entry.const_int_from_type(context, location, token_type_index, u64_type)?; - let cost_value_ptr = entry.append_op_result(llvm::get_element_ptr_dynamic( + let token_cost_value_ptr = entry.append_op_result(llvm::get_element_ptr_dynamic( context, builtin_ptr, &[token_type_index_val], @@ -134,10 +134,10 @@ pub fn build_withdraw_gas<'ctx, 'this>( pointer(context, 0), location, ))?; - let cost_value = entry.load(context, location, cost_value_ptr, u64_type)?; - let cost_value = entry.append_op_result(arith::extui(cost_value, u128_type, location))?; + let token_cost_multiplier_value = entry.load(context, location, token_cost_value_ptr, u64_type)?; + let token_cost_multiplier_value = entry.append_op_result(arith::extui(token_cost_multiplier_value, u128_type, location))?; let total_gas_cost_val = - entry.append_op_result(arith::muli(gas_cost_val, cost_value, location))?; + entry.append_op_result(arith::muli(gas_cost_val, token_cost_multiplier_value, location))?; final_gas_cost = entry.append_op_result(arith::addi(final_gas_cost, total_gas_cost_val, location))?; } @@ -158,7 +158,7 @@ pub fn build_withdraw_gas<'ctx, 'this>( context, is_enough, [0, 1], - [&[range_check, resulting_gas]; 2], + [&[range_check, resulting_gas], &[range_check, current_gas]], location, )); @@ -241,7 +241,7 @@ pub fn build_builtin_withdraw_gas<'ctx, 'this>( context, is_enough, [0, 1], - [&[range_check, resulting_gas]; 2], + [&[range_check, resulting_gas], &[range_check, current_gas]], location, )); From 8e48a501e692eb4de90f1ffc794741afa8168bd8 Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Tue, 22 Oct 2024 13:12:42 +0200 Subject: [PATCH 03/31] fix gas --- src/compiler.rs | 25 +++++++++---------- src/executor/contract.rs | 44 ++++++++++++++++++++++++++++++---- src/libfuncs/gas.rs | 16 +++++++++---- src/metadata/gas.rs | 30 +++++++++++++++++++++++ tests/common.rs | 17 ++++++++++++- tests/tests/starknet/keccak.rs | 13 +++++++++- 6 files changed, 121 insertions(+), 24 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index f5feac842..f4ec8b1c2 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -146,21 +146,18 @@ pub fn compile( )?; block.append_operation(melior::dialect::llvm::r#return(Some(value), location)); - module.body().append_operation( - { - let op = - ods::llvm::mlir_global( - context, - region, - TypeAttribute::new(llvm::r#type::pointer(context, 0)), - StringAttribute::new(context, "builtin_costs"), - Attribute::parse(context, "#llvm.linkage").unwrap(), - location, - ); + module.body().append_operation({ + let op = ods::llvm::mlir_global( + context, + region, + TypeAttribute::new(llvm::r#type::pointer(context, 0)), + StringAttribute::new(context, "builtin_costs"), + Attribute::parse(context, "#llvm.linkage").unwrap(), + location, + ); - op.into() - }, - ); + op.into() + }); } // Sierra programs have the following structure: diff --git a/src/executor/contract.rs b/src/executor/contract.rs index 5b050c432..0ebf1c8ff 100644 --- a/src/executor/contract.rs +++ b/src/executor/contract.rs @@ -37,6 +37,7 @@ use crate::{ error::{Error, Result}, execution_result::{BuiltinStats, ContractExecutionResult}, executor::invoke_trampoline, + metadata::gas::GasMetadata, module::NativeModule, starknet::{handler::StarknetSyscallHandlerCallbacks, StarknetSyscallHandler}, types::TypeBuilder, @@ -94,6 +95,7 @@ pub enum ContractInfoVersion { #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] pub struct EntryPointInfo { pub builtins: Vec, + pub initial_cost: BTreeMap, // cost token type offset, cost } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] @@ -144,9 +146,14 @@ impl AotContractExecutor { let NativeModule { module, registry, - metadata: _, + metadata, } = module; + let initial_gas_costs = { + let gas_meta: &GasMetadata = metadata.get().unwrap(); + gas_meta.initial_required_gas_for_entry_points() + }; + let mut infos = BTreeMap::new(); for x in &sierra_program.funcs { @@ -192,7 +199,13 @@ impl AotContractExecutor { } } - infos.insert(x.id.id, EntryPointInfo { builtins }); + infos.insert( + x.id.id, + EntryPointInfo { + builtins, + initial_cost: initial_gas_costs.get(&x.id.id).cloned().unwrap_or_default(), + }, + ); } let library_path = NamedTempFile::new()? @@ -261,12 +274,36 @@ impl AotContractExecutor { let builtin_costs = builtin_costs.unwrap_or_default(); let builtin_costs: [u64; 7] = builtin_costs.into(); + let initial_gas_cost = { + let mut cost = 0; + + for (offset, val) in self + .contract_info + .entry_points + .get(&function_id.id) + .unwrap() + .initial_cost + .iter() + { + let token_cost = builtin_costs[*offset as usize] * val; + cost += token_cost; + } + cost as u128 + }; + let gas = gas + .unwrap_or(initial_gas_cost) + .saturating_sub(initial_gas_cost); + unsafe { *builtin_costs_ptr.cast() = builtin_costs.as_ptr(); } // it can vary from contract to contract thats why we need to store/ load it. - let builtins_size: usize = self.contract_info.entry_points[&function_id.id].builtins.iter().map(|x| x.size_in_bytes()).sum(); + let builtins_size: usize = self.contract_info.entry_points[&function_id.id] + .builtins + .iter() + .map(|x| x.size_in_bytes()) + .sum(); // There is always a return ptr because contracts always return more than 1 thing (builtin counters, syscall, enum) let return_ptr = arena.alloc_layout(unsafe { @@ -282,7 +319,6 @@ impl AotContractExecutor { for b in &self.contract_info.entry_points[&function_id.id].builtins { match b { BuiltinType::Gas => { - let gas = gas.unwrap_or(0); gas.to_bytes(&mut invoke_data)?; } BuiltinType::BuiltinCosts => { diff --git a/src/libfuncs/gas.rs b/src/libfuncs/gas.rs index 40ddd1138..80140ce42 100644 --- a/src/libfuncs/gas.rs +++ b/src/libfuncs/gas.rs @@ -134,10 +134,18 @@ pub fn build_withdraw_gas<'ctx, 'this>( pointer(context, 0), location, ))?; - let token_cost_multiplier_value = entry.load(context, location, token_cost_value_ptr, u64_type)?; - let token_cost_multiplier_value = entry.append_op_result(arith::extui(token_cost_multiplier_value, u128_type, location))?; - let total_gas_cost_val = - entry.append_op_result(arith::muli(gas_cost_val, token_cost_multiplier_value, location))?; + let token_cost_multiplier_value = + entry.load(context, location, token_cost_value_ptr, u64_type)?; + let token_cost_multiplier_value = entry.append_op_result(arith::extui( + token_cost_multiplier_value, + u128_type, + location, + ))?; + let total_gas_cost_val = entry.append_op_result(arith::muli( + gas_cost_val, + token_cost_multiplier_value, + location, + ))?; final_gas_cost = entry.append_op_result(arith::addi(final_gas_cost, total_gas_cost_val, location))?; } diff --git a/src/metadata/gas.rs b/src/metadata/gas.rs index 9bb2ac34b..6dd1dff98 100644 --- a/src/metadata/gas.rs +++ b/src/metadata/gas.rs @@ -1,3 +1,5 @@ +use std::collections::BTreeMap; + use cairo_lang_runner::token_gas_cost; use cairo_lang_sierra::{ extensions::gas::CostTokenType, @@ -103,6 +105,34 @@ impl GasMetadata { ) } + pub fn initial_required_gas_for_entry_points(&self) -> BTreeMap> { + self.gas_info + .function_costs + .iter() + .map(|func| { + (func.0.id, { + let mut costs = BTreeMap::new(); + + for (token, val) in func.1.iter() { + let offset: u64 = match token { + CostTokenType::Const => 0, + CostTokenType::Pedersen => 1, + CostTokenType::Bitwise => 2, + CostTokenType::EcOp => 3, + CostTokenType::Poseidon => 4, + CostTokenType::AddMod => 5, + CostTokenType::MulMod => 6, + _ => unreachable!(), + }; + costs.insert(offset, *val as u64); + } + + costs + }) + }) + .collect() + } + pub fn get_gas_costs_for_statement(&self, idx: StatementIdx) -> Vec<(u128, CostTokenType)> { let mut costs = Vec::new(); for cost_type in CostTokenType::iter_casm_tokens() { diff --git a/tests/common.rs b/tests/common.rs index b35a85e18..3645cd7c8 100644 --- a/tests/common.rs +++ b/tests/common.rs @@ -31,7 +31,7 @@ use cairo_lang_starknet_classes::{ use cairo_native::{ context::NativeContext, execution_result::{ContractExecutionResult, ExecutionResult}, - executor::JitNativeExecutor, + executor::{AotContractExecutor, JitNativeExecutor}, starknet::{DummySyscallHandler, StarknetSyscallHandler}, utils::{find_entry_point_by_idx, HALF_PRIME, PRIME}, OptLevel, Value, @@ -433,6 +433,21 @@ pub fn run_native_starknet_contract( .expect("failed to execute the given contract") } +pub fn run_native_starknet_aot_contract( + sierra_program: &Program, + entry_point_function_idx: usize, + args: &[Felt], + handler: impl StarknetSyscallHandler, +) -> ContractExecutionResult { + let entry_point_fn = find_entry_point_by_idx(sierra_program, entry_point_function_idx).unwrap(); + let entry_point_id = &entry_point_fn.id; + + let native_executor = AotContractExecutor::new(sierra_program, Default::default()).unwrap(); + native_executor + .run(entry_point_id, args, u128::MAX.into(), None, handler) + .expect("failed to execute the given contract") +} + /// Given the result of the cairo-vm and cairo-native of the same program, it compares /// the results automatically, triggering a proptest assert if there is a mismatch. /// diff --git a/tests/tests/starknet/keccak.rs b/tests/tests/starknet/keccak.rs index 9422ef6fe..55e2f102a 100644 --- a/tests/tests/starknet/keccak.rs +++ b/tests/tests/starknet/keccak.rs @@ -1,4 +1,4 @@ -use crate::common::run_native_starknet_contract; +use crate::common::{run_native_starknet_aot_contract, run_native_starknet_contract}; use cairo_lang_compiler::CompilerConfig; use cairo_lang_starknet::compile::compile_path; use cairo_native::starknet_stub::StubSyscallHandler; @@ -41,4 +41,15 @@ fn keccak_test() { 340282366920938463463374607431768143515 ); assert_eq!(result.return_values, vec![1.into()]); + + let result_aot_ct = run_native_starknet_aot_contract( + &program, + entry_point.function_idx, + &[], + &mut StubSyscallHandler::default(), + ); + + assert!(!result_aot_ct.failure_flag); + assert_eq!(result_aot_ct.remaining_gas, result.remaining_gas); + assert_eq!(result_aot_ct.return_values, vec![1.into()]); } From 11aa07f2dba1ad108b776d9ca403c73347eb34b9 Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Wed, 23 Oct 2024 14:25:05 +0200 Subject: [PATCH 04/31] add paralel test --- Cargo.lock | 1 + Cargo.toml | 1 + src/executor/contract.rs | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 34 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 6033835da..94ef09486 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -987,6 +987,7 @@ dependencies = [ "num-traits 0.2.19", "pretty_assertions_sorted", "proptest", + "rayon", "rstest", "scarb-metadata", "scarb-ui", diff --git a/Cargo.toml b/Cargo.toml index 86d28cac7..cd5988623 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -131,6 +131,7 @@ rstest = "0.23.0" test-case = "3.3" walkdir = "2.5.0" serde_json = { version = "1.0.128" } +rayon = "1.10.0" [build-dependencies] cc = "1.1.28" diff --git a/src/executor/contract.rs b/src/executor/contract.rs index 0ebf1c8ff..8c525e49a 100644 --- a/src/executor/contract.rs +++ b/src/executor/contract.rs @@ -552,6 +552,7 @@ mod tests { use super::*; use crate::{starknet_stub::StubSyscallHandler, utils::test::load_starknet}; use cairo_lang_sierra::program::Program; + use rayon::iter::ParallelBridge; use rstest::*; #[fixture] @@ -601,6 +602,37 @@ mod tests { program } + #[rstest] + #[case(OptLevel::Default)] + fn test_contract_executor_parallel(starknet_program: Program, #[case] optlevel: OptLevel) { + use rayon::iter::ParallelIterator; + + let executor = Arc::new(AotContractExecutor::new(&starknet_program, optlevel).unwrap()); + + // The last function in the program is the `get` wrapper function. + let entrypoint_function_id = starknet_program + .funcs + .last() + .expect("should have a function") + .id + .clone(); + + (0..200).par_bridge().for_each(|n| { + let result = executor + .run( + &entrypoint_function_id, + &[n.into()], + Some(u64::MAX as u128), + None, + &mut StubSyscallHandler::default(), + ) + .unwrap(); + + assert_eq!(result.return_values, vec![Felt::from(n), Felt::from(n * 2)]); + assert_eq!(result.remaining_gas, 18446744073709548175); + }); + } + #[rstest] #[case(OptLevel::None)] #[case(OptLevel::Default)] From f2b7d32ed4e79135d3f8c1bc6d0cd47b89590603 Mon Sep 17 00:00:00 2001 From: Edgar Date: Mon, 28 Oct 2024 14:58:54 +0100 Subject: [PATCH 05/31] Add entry point info to AotContractExecutor (#889) * store entry point info, optimize abi storage * use felt * update hash --- .github/workflows/starknet-blocks.yml | 2 +- src/error.rs | 3 + src/executor/contract.rs | 147 ++++++++++++++++++-------- src/utils.rs | 52 ++++++++- tests/common.rs | 18 ++-- tests/tests/starknet/keccak.rs | 4 +- 6 files changed, 172 insertions(+), 54 deletions(-) diff --git a/.github/workflows/starknet-blocks.yml b/.github/workflows/starknet-blocks.yml index 492c621a3..7085fb2d7 100644 --- a/.github/workflows/starknet-blocks.yml +++ b/.github/workflows/starknet-blocks.yml @@ -75,7 +75,7 @@ jobs: uses: actions/checkout@v4 with: repository: lambdaclass/starknet-replay - ref: 08aa133b11e1e319036354c9acd8270483c844b5 + ref: 53542995b1671b6cc16bdf87b0b5a10a6fd801a4 path: replay - name: Install Starknet Replay deps diff --git a/src/error.rs b/src/error.rs index 2cc503d07..c093488c6 100644 --- a/src/error.rs +++ b/src/error.rs @@ -72,6 +72,9 @@ pub enum Error { #[error("missing BuiltinCosts global symbol, should never happen, this is a bug")] MissingBuiltinCostsSymbol, + #[error("selector not found in the AotContractExecutor mappings")] + SelectorNotFound, + #[error(transparent)] IoError(#[from] std::io::Error), diff --git a/src/executor/contract.rs b/src/executor/contract.rs index 8c525e49a..93a925a72 100644 --- a/src/executor/contract.rs +++ b/src/executor/contract.rs @@ -56,13 +56,14 @@ use cairo_lang_sierra::{ ids::FunctionId, program::Program, }; +use cairo_lang_starknet_classes::contract_class::ContractEntryPoints; use educe::Educe; use libloading::Library; use serde::{Deserialize, Serialize}; use starknet_types_core::felt::Felt; use std::{ alloc::Layout, - collections::BTreeMap, + collections::{BTreeMap, HashSet}, ffi::c_void, path::{Path, PathBuf}, ptr::NonNull, @@ -78,13 +79,14 @@ pub struct AotContractExecutor { library: Arc, path: PathBuf, is_temp_path: bool, - contract_info: ContractInfo, + contract_info: NativeContractInfo, } -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] -pub struct ContractInfo { +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] +pub struct NativeContractInfo { pub version: ContractInfoVersion, - pub entry_points: BTreeMap, + pub entry_points_info: BTreeMap, + pub entry_point_selector_to_id: BTreeMap, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] @@ -139,7 +141,11 @@ impl AotContractExecutor { /// If not saved, the path is treated as /// a temporary file an deleted when dropped. /// If you loaded a ContractExecutor using [`load`] then it will not be treated as a temp file. - pub fn new(sierra_program: &Program, opt_level: OptLevel) -> Result { + pub fn new( + sierra_program: &Program, + entry_points: &ContractEntryPoints, + opt_level: OptLevel, + ) -> Result { let native_context = NativeContext::new(); let module = native_context.compile(sierra_program, true)?; @@ -156,7 +162,26 @@ impl AotContractExecutor { let mut infos = BTreeMap::new(); + let mut entry_point_selector_to_id = BTreeMap::new(); + + let mut used_function_ids = HashSet::new(); + for entry in entry_points + .constructor + .iter() + .chain(entry_points.external.iter()) + .chain(entry_points.l1_handler.iter()) + { + entry_point_selector_to_id + .insert(Felt::from(&entry.selector), entry.function_idx as u64); + used_function_ids.insert(entry.function_idx as u64); + } + for x in &sierra_program.funcs { + // Avoid storing function info for methods that are not contract entry points. + if !used_function_ids.contains(&x.id.id) { + continue; + } + let mut builtins = Vec::new(); for p in &x.params { @@ -220,9 +245,10 @@ impl AotContractExecutor { library: Arc::new(unsafe { Library::new(&library_path)? }), path: library_path, is_temp_path: true, - contract_info: ContractInfo { + contract_info: NativeContractInfo { version: ContractInfoVersion::Version0, - entry_points: infos, + entry_points_info: infos, + entry_point_selector_to_id, }, }) } @@ -245,7 +271,7 @@ impl AotContractExecutor { /// Load the executor from an already compiled library with the additional info json file. pub fn load(library_path: &Path) -> Result { let info_str = std::fs::read_to_string(library_path.with_extension("json"))?; - let contract_info: ContractInfo = serde_json::from_str(&info_str)?; + let contract_info: NativeContractInfo = serde_json::from_str(&info_str)?; Ok(Self { library: Arc::new(unsafe { Library::new(library_path)? }), path: library_path.to_path_buf(), @@ -257,7 +283,7 @@ impl AotContractExecutor { /// Runs the given entry point. pub fn run( &self, - function_id: &FunctionId, + selector: Felt, args: &[Felt], gas: Option, builtin_costs: Option, @@ -266,7 +292,15 @@ impl AotContractExecutor { let arena = Bump::new(); let mut invoke_data = Vec::::new(); - let function_ptr = self.find_function_ptr(function_id, true)?; + let function_id = FunctionId { + id: *self + .contract_info + .entry_point_selector_to_id + .get(&selector) + .ok_or(Error::SelectorNotFound)?, + debug_name: None, + }; + let function_ptr = self.find_function_ptr(&function_id, true)?; let builtin_costs_ptr = self .find_symbol_ptr("builtin_costs") .ok_or_else(|| Error::MissingBuiltinCostsSymbol)?; @@ -279,7 +313,7 @@ impl AotContractExecutor { for (offset, val) in self .contract_info - .entry_points + .entry_points_info .get(&function_id.id) .unwrap() .initial_cost @@ -299,7 +333,7 @@ impl AotContractExecutor { } // it can vary from contract to contract thats why we need to store/ load it. - let builtins_size: usize = self.contract_info.entry_points[&function_id.id] + let builtins_size: usize = self.contract_info.entry_points_info[&function_id.id] .builtins .iter() .map(|x| x.size_in_bytes()) @@ -316,7 +350,7 @@ impl AotContractExecutor { let mut syscall_handler = StarknetSyscallHandlerCallbacks::new(&mut syscall_handler); - for b in &self.contract_info.entry_points[&function_id.id].builtins { + for b in &self.contract_info.entry_points_info[&function_id.id].builtins { match b { BuiltinType::Gas => { gas.to_bytes(&mut invoke_data)?; @@ -398,7 +432,7 @@ impl AotContractExecutor { let return_ptr = &mut return_ptr.cast(); - for b in &self.contract_info.entry_points[&function_id.id].builtins { + for b in &self.contract_info.entry_points_info[&function_id.id].builtins { match b { BuiltinType::Gas => { remaining_gas = unsafe { *read_value::(return_ptr) }; @@ -550,14 +584,14 @@ impl Drop for AotContractExecutor { #[cfg(test)] mod tests { use super::*; - use crate::{starknet_stub::StubSyscallHandler, utils::test::load_starknet}; - use cairo_lang_sierra::program::Program; + use crate::{starknet_stub::StubSyscallHandler, utils::test::load_starknet_contract}; + use cairo_lang_starknet_classes::contract_class::ContractClass; use rayon::iter::ParallelBridge; use rstest::*; #[fixture] - fn starknet_program() -> Program { - let (_, program) = load_starknet! { + fn starknet_program() -> ContractClass { + let (_, program) = load_starknet_contract! { #[starknet::interface] trait ISimpleStorage { fn get(self: @TContractState, x: felt252) -> (felt252, felt252); @@ -580,8 +614,8 @@ mod tests { } #[fixture] - fn starknet_program_empty() -> Program { - let (_, program) = load_starknet! { + fn starknet_program_empty() -> ContractClass { + let (_, program) = load_starknet_contract! { #[starknet::interface] trait ISimpleStorage { fn call(self: @TContractState); @@ -604,23 +638,34 @@ mod tests { #[rstest] #[case(OptLevel::Default)] - fn test_contract_executor_parallel(starknet_program: Program, #[case] optlevel: OptLevel) { + fn test_contract_executor_parallel( + starknet_program: ContractClass, + #[case] optlevel: OptLevel, + ) { use rayon::iter::ParallelIterator; - let executor = Arc::new(AotContractExecutor::new(&starknet_program, optlevel).unwrap()); + let executor = Arc::new( + AotContractExecutor::new( + &starknet_program.extract_sierra_program().unwrap(), + &starknet_program.entry_points_by_type, + optlevel, + ) + .unwrap(), + ); // The last function in the program is the `get` wrapper function. - let entrypoint_function_id = starknet_program - .funcs + let selector = starknet_program + .entry_points_by_type + .external .last() - .expect("should have a function") - .id + .unwrap() + .selector .clone(); (0..200).par_bridge().for_each(|n| { let result = executor .run( - &entrypoint_function_id, + Felt::from(&selector), &[n.into()], Some(u64::MAX as u128), None, @@ -636,19 +681,26 @@ mod tests { #[rstest] #[case(OptLevel::None)] #[case(OptLevel::Default)] - fn test_contract_executor(starknet_program: Program, #[case] optlevel: OptLevel) { - let executor = AotContractExecutor::new(&starknet_program, optlevel).unwrap(); + fn test_contract_executor(starknet_program: ContractClass, #[case] optlevel: OptLevel) { + let executor = AotContractExecutor::new( + &starknet_program.extract_sierra_program().unwrap(), + &starknet_program.entry_points_by_type, + optlevel, + ) + .unwrap(); // The last function in the program is the `get` wrapper function. - let entrypoint_function_id = &starknet_program - .funcs + let selector = starknet_program + .entry_points_by_type + .external .last() - .expect("should have a function") - .id; + .unwrap() + .selector + .clone(); let result = executor .run( - entrypoint_function_id, + Felt::from(&selector), &[2.into()], Some(u64::MAX as u128), None, @@ -662,19 +714,30 @@ mod tests { #[rstest] #[case(OptLevel::None)] #[case(OptLevel::Default)] - fn test_contract_executor_empty(starknet_program_empty: Program, #[case] optlevel: OptLevel) { - let executor = AotContractExecutor::new(&starknet_program_empty, optlevel).unwrap(); + fn test_contract_executor_empty( + starknet_program_empty: ContractClass, + #[case] optlevel: OptLevel, + ) { + let executor = AotContractExecutor::new( + &starknet_program_empty.extract_sierra_program().unwrap(), + &starknet_program_empty.entry_points_by_type, + optlevel, + ) + .unwrap(); // The last function in the program is the `get` wrapper function. - let entrypoint_function_id = &starknet_program_empty - .funcs + // The last function in the program is the `get` wrapper function. + let selector = starknet_program_empty + .entry_points_by_type + .external .last() - .expect("should have a function") - .id; + .unwrap() + .selector + .clone(); let result = executor .run( - entrypoint_function_id, + Felt::from(&selector), &[], Some(u64::MAX as u128), None, diff --git a/src/utils.rs b/src/utils.rs index 090b03292..d243e16ec 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -517,7 +517,8 @@ pub mod test { program::Program, program::{FunctionSignature, GenFunction, StatementIdx}, }; - use cairo_lang_starknet::starknet_plugin_suite; + use cairo_lang_starknet::{compile::compile_contract_in_prepared_db, starknet_plugin_suite}; + use cairo_lang_starknet_classes::contract_class::ContractClass; use pretty_assertions_sorted::assert_eq; use std::io::Write; use std::{env::var, fmt::Formatter, fs, path::Path}; @@ -532,8 +533,14 @@ pub mod test { $crate::utils::test::load_starknet_str(stringify!($($program)+)) }; } + macro_rules! load_starknet_contract { + ( $( $program:tt )+ ) => { + $crate::utils::test::load_starknet_contract_str(stringify!($($program)+)) + }; + } pub(crate) use load_cairo; pub(crate) use load_starknet; + pub(crate) use load_starknet_contract; // Helper macros for faster testing. macro_rules! jit_struct { @@ -592,6 +599,49 @@ pub mod test { ) } + pub(crate) fn load_starknet_contract_str(program_str: &str) -> (String, ContractClass) { + compile_contract( + program_str, + RootDatabase::builder() + .with_plugin_suite(starknet_plugin_suite()) + .build() + .unwrap(), + ) + } + + pub(crate) fn compile_contract( + program_str: &str, + mut db: RootDatabase, + ) -> (String, ContractClass) { + let mut program_file = tempfile::Builder::new() + .prefix("test_") + .suffix(".cairo") + .tempfile() + .unwrap(); + fs::write(&mut program_file, program_str).unwrap(); + + init_dev_corelib( + &mut db, + Path::new(&var("CARGO_MANIFEST_DIR").unwrap()).join("corelib/src"), + ); + let main_crate_ids = setup_project(&mut db, program_file.path()).unwrap(); + let contract = compile_contract_in_prepared_db( + &db, + None, + main_crate_ids, + CompilerConfig { + diagnostics_reporter: DiagnosticsReporter::stderr(), + replace_ids: true, + ..Default::default() + }, + ) + .unwrap(); + + let module_name = program_file.path().with_extension(""); + let module_name = module_name.file_name().unwrap().to_str().unwrap(); + (module_name.to_string(), contract) + } + pub(crate) fn compile_program(program_str: &str, mut db: RootDatabase) -> (String, Program) { let mut program_file = tempfile::Builder::new() .prefix("test_") diff --git a/tests/common.rs b/tests/common.rs index 3645cd7c8..6a72c0f0e 100644 --- a/tests/common.rs +++ b/tests/common.rs @@ -48,7 +48,7 @@ use lambdaworks_math::{ }, unsigned_integer::element::UnsignedInteger, }; -use num_bigint::{BigInt, Sign}; +use num_bigint::{BigInt, BigUint, Sign}; use proptest::{strategy::Strategy, test_runner::TestCaseError}; use starknet_types_core::felt::Felt; use std::{collections::HashMap, env::var, fs, ops::Neg, path::Path}; @@ -434,17 +434,19 @@ pub fn run_native_starknet_contract( } pub fn run_native_starknet_aot_contract( - sierra_program: &Program, - entry_point_function_idx: usize, + contract: &ContractClass, + selector: &BigUint, args: &[Felt], handler: impl StarknetSyscallHandler, ) -> ContractExecutionResult { - let entry_point_fn = find_entry_point_by_idx(sierra_program, entry_point_function_idx).unwrap(); - let entry_point_id = &entry_point_fn.id; - - let native_executor = AotContractExecutor::new(sierra_program, Default::default()).unwrap(); + let native_executor = AotContractExecutor::new( + &contract.extract_sierra_program().unwrap(), + &contract.entry_points_by_type, + Default::default(), + ) + .unwrap(); native_executor - .run(entry_point_id, args, u128::MAX.into(), None, handler) + .run(Felt::from(selector), args, u128::MAX.into(), None, handler) .expect("failed to execute the given contract") } diff --git a/tests/tests/starknet/keccak.rs b/tests/tests/starknet/keccak.rs index 55e2f102a..a2365ab8c 100644 --- a/tests/tests/starknet/keccak.rs +++ b/tests/tests/starknet/keccak.rs @@ -43,8 +43,8 @@ fn keccak_test() { assert_eq!(result.return_values, vec![1.into()]); let result_aot_ct = run_native_starknet_aot_contract( - &program, - entry_point.function_idx, + contract, + &entry_point.selector, &[], &mut StubSyscallHandler::default(), ); From 8bb356c41523e04bf73df270f3c06886f37b112b Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Tue, 29 Oct 2024 12:01:17 +0100 Subject: [PATCH 06/31] upd replay --- .github/workflows/starknet-blocks.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/starknet-blocks.yml b/.github/workflows/starknet-blocks.yml index 3b07d1f6c..1d336ed7a 100644 --- a/.github/workflows/starknet-blocks.yml +++ b/.github/workflows/starknet-blocks.yml @@ -74,7 +74,7 @@ jobs: uses: actions/checkout@v4 with: repository: lambdaclass/starknet-replay - ref: 53542995b1671b6cc16bdf87b0b5a10a6fd801a4 + ref: b46fcc79b839948636901d189a3c1e7d0832f831 path: replay - name: Install Starknet Replay deps From 899a6b044b0ab2a4fa20794057f2bf12f669b465 Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Tue, 29 Oct 2024 14:36:34 +0100 Subject: [PATCH 07/31] try with thread local --- src/compiler.rs | 68 ++++++++++++++++++++++++++++++++++++++-- src/executor.rs | 16 +++------- src/executor/aot.rs | 33 +++++++++++++++++-- src/executor/contract.rs | 17 +++++----- src/executor/jit.rs | 18 ++++++++--- src/libfuncs/gas.rs | 32 +++++++++++++++++-- src/utils.rs | 2 +- tests/common.rs | 4 +-- 8 files changed, 155 insertions(+), 35 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index f4ec8b1c2..b2509d54d 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -73,7 +73,7 @@ use melior::{ dialect::{ arith::CmpiPredicate, cf, func, index, - llvm::{self, LoadStoreOptions}, + llvm::{self, r#type::pointer, LoadStoreOptions}, memref, ods, }, ir::{ @@ -147,17 +147,79 @@ pub fn compile( block.append_operation(melior::dialect::llvm::r#return(Some(value), location)); module.body().append_operation({ - let op = ods::llvm::mlir_global( + let mut op = ods::llvm::mlir_global( context, region, TypeAttribute::new(llvm::r#type::pointer(context, 0)), StringAttribute::new(context, "builtin_costs"), - Attribute::parse(context, "#llvm.linkage").unwrap(), + Attribute::parse(context, "#llvm.linkage").unwrap(), location, ); + op.set_thread_local(Attribute::unit(context)); op.into() }); + + module.body().append_operation({ + llvm::func( + context, + StringAttribute::new(context, "internal_set_builtin_costs"), + TypeAttribute::new(llvm::r#type::function( + llvm::r#type::void(context), + &[pointer(context, 0)], + false, + )), + { + let region = Region::new(); + + let entry = region.append_block(Block::new(&[(pointer(context, 0), location)])); + + let global = entry.append_op_result( + ods::llvm::mlir_addressof( + context, + pointer(context, 0), + FlatSymbolRefAttribute::new(context, "builtin_costs"), + location, + ) + .into(), + )?; + let thread_local_ptr = entry.append_op_result( + ods::llvm::intr_threadlocal_address( + context, + pointer(context, 0), + global, + location, + ) + .into(), + )?; + entry.store( + context, + location, + thread_local_ptr, + entry.argument(0)?.into(), + )?; + + entry.append_operation(llvm::r#return(None, location)); + + region + }, + &[ + ( + Identifier::new(context, "sym_visibility"), + StringAttribute::new(context, "public").into(), + ), + ( + Identifier::new(context, "linkage"), + Attribute::parse(context, "#llvm.linkage").unwrap(), + ), + ( + Identifier::new(context, "CConv"), + Attribute::parse(context, "#llvm.cconv").unwrap(), + ), + ], + location, + ) + }); } // Sierra programs have the following structure: diff --git a/src/executor.rs b/src/executor.rs index 914a1562e..6625690cf 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -69,7 +69,7 @@ extern "C" { fn invoke_dynamic( registry: &ProgramRegistry, function_ptr: *const c_void, - builtin_costs_ptr: Option<*mut c_void>, + builtin_costs_setter_ptr: extern "C" fn(*const u64), function_signature: &FunctionSignature, args: &[Value], gas: u128, @@ -145,11 +145,8 @@ fn invoke_dynamic( // Order matters, for the libfunc impl let builtin_costs: [u64; 7] = BuiltinCosts::default().into(); - if let Some(builtin_costs_ptr) = builtin_costs_ptr { - unsafe { - *builtin_costs_ptr.cast() = builtin_costs.as_ptr(); - } - } + // set the builtin costs using the utility method to set the thread local + builtin_costs_setter_ptr(builtin_costs.as_ptr()); // Generate argument list. let mut iter = args.iter(); @@ -177,11 +174,8 @@ fn invoke_dynamic( .to_bytes(&mut invoke_data)?; } CoreTypeConcrete::BuiltinCosts(_) => { - if let Some(builtin_costs_ptr) = builtin_costs_ptr { - builtin_costs_ptr.to_bytes(&mut invoke_data)?; - } else { - (builtin_costs.as_ptr()).to_bytes(&mut invoke_data)?; - } + // todo: check if valid + (builtin_costs.as_ptr()).to_bytes(&mut invoke_data)?; } type_info if type_info.is_builtin() => 0u64.to_bytes(&mut invoke_data)?, type_info => ValueWithInfoWrapper { diff --git a/src/executor/aot.rs b/src/executor/aot.rs index ebaed4c3e..8b1e903bf 100644 --- a/src/executor/aot.rs +++ b/src/executor/aot.rs @@ -78,10 +78,19 @@ impl AotNativeExecutor { .get_initial_available_gas(function_id, gas) .map_err(crate::error::Error::GasMetadataError)?; + let builtin_setter_ptr = unsafe { + std::mem::transmute::<*mut libc::c_void, extern "C" fn(*const u64)>( + self.library + .get::(b"internal_set_builtin_costs")? + .into_raw() + .into_raw(), + ) + }; + super::invoke_dynamic( &self.registry, self.find_function_ptr(function_id), - self.find_symbol_ptr("builtin_costs"), + builtin_setter_ptr, self.extract_signature(function_id), args, available_gas, @@ -101,10 +110,19 @@ impl AotNativeExecutor { .get_initial_available_gas(function_id, gas) .map_err(crate::error::Error::GasMetadataError)?; + let builtin_setter_ptr = unsafe { + std::mem::transmute::<*mut libc::c_void, extern "C" fn(*const u64)>( + self.library + .get::(b"internal_set_builtin_costs")? + .into_raw() + .into_raw(), + ) + }; + super::invoke_dynamic( &self.registry, self.find_function_ptr(function_id), - self.find_symbol_ptr("builtin_costs"), + builtin_setter_ptr, self.extract_signature(function_id), args, available_gas, @@ -124,10 +142,19 @@ impl AotNativeExecutor { .get_initial_available_gas(function_id, gas) .map_err(crate::error::Error::GasMetadataError)?; + let builtin_setter_ptr = unsafe { + std::mem::transmute::<*mut libc::c_void, extern "C" fn(*const u64)>( + self.library + .get::(b"internal_set_builtin_costs")? + .into_raw() + .into_raw(), + ) + }; + ContractExecutionResult::from_execution_result(super::invoke_dynamic( &self.registry, self.find_function_ptr(function_id), - self.find_symbol_ptr("builtin_costs"), + builtin_setter_ptr, self.extract_signature(function_id), &[Value::Struct { fields: vec![Value::Array( diff --git a/src/executor/contract.rs b/src/executor/contract.rs index 93a925a72..ec11144b8 100644 --- a/src/executor/contract.rs +++ b/src/executor/contract.rs @@ -301,12 +301,16 @@ impl AotContractExecutor { debug_name: None, }; let function_ptr = self.find_function_ptr(&function_id, true)?; - let builtin_costs_ptr = self - .find_symbol_ptr("builtin_costs") - .ok_or_else(|| Error::MissingBuiltinCostsSymbol)?; + + let builtin_setter_ptr = unsafe { + self.library + .get::(b"internal_set_builtin_costs")? + }; let builtin_costs = builtin_costs.unwrap_or_default(); let builtin_costs: [u64; 7] = builtin_costs.into(); + // set the builtin costs using the utility method to set the thread local + builtin_setter_ptr(builtin_costs.as_ptr()); let initial_gas_cost = { let mut cost = 0; @@ -328,10 +332,6 @@ impl AotContractExecutor { .unwrap_or(initial_gas_cost) .saturating_sub(initial_gas_cost); - unsafe { - *builtin_costs_ptr.cast() = builtin_costs.as_ptr(); - } - // it can vary from contract to contract thats why we need to store/ load it. let builtins_size: usize = self.contract_info.entry_points_info[&function_id.id] .builtins @@ -356,7 +356,8 @@ impl AotContractExecutor { gas.to_bytes(&mut invoke_data)?; } BuiltinType::BuiltinCosts => { - builtin_costs_ptr.to_bytes(&mut invoke_data)?; + // todo: check if valid + builtin_costs.as_ptr().to_bytes(&mut invoke_data)?; } BuiltinType::System => { (&mut syscall_handler as *mut StarknetSyscallHandlerCallbacks<_>) diff --git a/src/executor/jit.rs b/src/executor/jit.rs index 4b50ce113..41a73115d 100644 --- a/src/executor/jit.rs +++ b/src/executor/jit.rs @@ -76,10 +76,13 @@ impl<'m> JitNativeExecutor<'m> { .get_initial_available_gas(function_id, gas) .map_err(crate::error::Error::GasMetadataError)?; + let builtin_setter_ptr: extern "C" fn(*const u64) = + unsafe { std::mem::transmute(self.engine.lookup("internal_set_builtin_costs")) }; + super::invoke_dynamic( &self.registry, self.find_function_ptr(function_id), - self.find_symbol_ptr("builtin_costs"), + builtin_setter_ptr, self.extract_signature(function_id).unwrap(), args, available_gas, @@ -100,10 +103,13 @@ impl<'m> JitNativeExecutor<'m> { .get_initial_available_gas(function_id, gas) .map_err(crate::error::Error::GasMetadataError)?; + let builtin_setter_ptr: extern "C" fn(*const u64) = + unsafe { std::mem::transmute(self.engine.lookup("internal_set_builtin_costs")) }; + super::invoke_dynamic( &self.registry, self.find_function_ptr(function_id), - self.find_symbol_ptr("builtin_costs"), + builtin_setter_ptr, self.extract_signature(function_id).unwrap(), args, available_gas, @@ -122,17 +128,19 @@ impl<'m> JitNativeExecutor<'m> { .gas_metadata .get_initial_available_gas(function_id, gas) .map_err(crate::error::Error::GasMetadataError)?; - // TODO: Check signature for contract interface. + + let builtin_setter_ptr: extern "C" fn(*const u64) = + unsafe { std::mem::transmute(self.engine.lookup("internal_set_builtin_costs")) }; + ContractExecutionResult::from_execution_result(super::invoke_dynamic( &self.registry, self.find_function_ptr(function_id), - self.find_symbol_ptr("builtin_costs"), + builtin_setter_ptr, self.extract_signature(function_id).unwrap(), &[Value::Struct { fields: vec![Value::Array( args.iter().cloned().map(Value::Felt252).collect(), )], - // TODO: Populate `debug_name`. debug_name: None, }], available_gas, diff --git a/src/libfuncs/gas.rs b/src/libfuncs/gas.rs index 80140ce42..0cf4f8c76 100644 --- a/src/libfuncs/gas.rs +++ b/src/libfuncs/gas.rs @@ -101,8 +101,22 @@ pub fn build_withdraw_gas<'ctx, 'this>( ) .into(), )?; + let thread_local_builtin_ptr_ptr = entry.append_op_result( + ods::llvm::intr_threadlocal_address( + context, + pointer(context, 0), + builtin_ptr_ptr, + location, + ) + .into(), + )?; - let builtin_ptr = entry.load(context, location, builtin_ptr_ptr, pointer(context, 0))?; + let builtin_ptr = entry.load( + context, + location, + thread_local_builtin_ptr_ptr, + pointer(context, 0), + )?; let mut final_gas_cost = entry.const_int_from_type(context, location, 0, u128_type)?; @@ -284,8 +298,22 @@ pub fn build_get_builtin_costs<'ctx, 'this>( ) .into(), )?; + let thread_local_builtin_ptr_ptr = entry.append_op_result( + ods::llvm::intr_threadlocal_address( + context, + pointer(context, 0), + builtin_ptr_ptr, + location, + ) + .into(), + )?; - let builtin_ptr = entry.load(context, location, builtin_ptr_ptr, builtin_costs_ty)?; + let builtin_ptr = entry.load( + context, + location, + thread_local_builtin_ptr_ptr, + builtin_costs_ty, + )?; entry.append_operation(helper.br(0, &[builtin_ptr], location)); diff --git a/src/utils.rs b/src/utils.rs index 400d2013a..90a315860 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -271,7 +271,7 @@ pub fn create_engine( opt_level: OptLevel, ) -> ExecutionEngine { // Create the JIT engine. - let engine = ExecutionEngine::new(module, opt_level.into(), &[], false); + let engine = ExecutionEngine::new(module, opt_level.into(), &[""], false); #[cfg(feature = "with-runtime")] register_runtime_symbols(&engine); diff --git a/tests/common.rs b/tests/common.rs index 6a72c0f0e..d2231ed4b 100644 --- a/tests/common.rs +++ b/tests/common.rs @@ -31,7 +31,7 @@ use cairo_lang_starknet_classes::{ use cairo_native::{ context::NativeContext, execution_result::{ContractExecutionResult, ExecutionResult}, - executor::{AotContractExecutor, JitNativeExecutor}, + executor::{AotContractExecutor, AotNativeExecutor, JitNativeExecutor}, starknet::{DummySyscallHandler, StarknetSyscallHandler}, utils::{find_entry_point_by_idx, HALF_PRIME, PRIME}, OptLevel, Value, @@ -427,7 +427,7 @@ pub fn run_native_starknet_contract( let entry_point_fn = find_entry_point_by_idx(sierra_program, entry_point_function_idx).unwrap(); let entry_point_id = &entry_point_fn.id; - let native_executor = JitNativeExecutor::from_native_module(native_program, Default::default()); + let native_executor = AotNativeExecutor::from_native_module(native_program, Default::default()); native_executor .invoke_contract_dynamic(entry_point_id, args, u128::MAX.into(), handler) .expect("failed to execute the given contract") From a72a146608e3c2407a757e9889c89baf97c66ca5 Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Wed, 30 Oct 2024 15:50:56 +0100 Subject: [PATCH 08/31] try to fix with thread local in runtime2 --- runtime/src/lib.rs | 27 ++++++++- src/compiler.rs | 91 +----------------------------- src/executor.rs | 6 +- src/executor/aot.rs | 32 ++++++----- src/executor/contract.rs | 11 ++-- src/executor/jit.rs | 18 +++--- src/ffi.rs | 3 +- src/libfuncs/gas.rs | 95 +++++++++----------------------- src/metadata/runtime_bindings.rs | 44 +++++++++++++++ src/utils.rs | 12 ++++ 10 files changed, 147 insertions(+), 192 deletions(-) diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 5e2c75ae7..49130afe3 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -14,7 +14,8 @@ use starknet_types_core::{ hash::StarkHash, }; use std::{ - collections::HashMap, ffi::c_void, fs::File, io::Write, mem::ManuallyDrop, os::fd::FromRawFd, + cell::Cell, collections::HashMap, ffi::c_void, fs::File, io::Write, mem::ManuallyDrop, + os::fd::FromRawFd, ptr::null, }; use std::{ops::Mul, vec::IntoIter}; @@ -475,6 +476,30 @@ pub unsafe extern "C" fn cairo_native__libfunc__ec__ec_state_try_finalize_nz( } } +thread_local! { + // We can use cell because a ptr is copy. + static BUILTIN_COSTS: Cell<*const u64> = const { + Cell::new(null()) + }; +} + +/// Store the gas builtin in the internal thread local. +/// Not a runtime metadata method, it should be called before the program is executed. +#[no_mangle] +pub extern "C" fn cairo_native__set_costs_builtin(ptr: *const u64) { + BUILTIN_COSTS.set(ptr); +} + +/// Get the gas builtin from the internal thread local. +#[no_mangle] +pub extern "C" fn cairo_native__get_costs_builtin() -> *const u64 { + if BUILTIN_COSTS.get().is_null() { + // We shouldn't panic here, but we can print a big message. + eprintln!("BUILTIN_COSTS POINTER IS NULL!"); + } + BUILTIN_COSTS.get() +} + /// Utility methods for the print runtime function /// Formats the given felts as a debug string. diff --git a/src/compiler.rs b/src/compiler.rs index b2509d54d..e6d217516 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -73,8 +73,8 @@ use melior::{ dialect::{ arith::CmpiPredicate, cf, func, index, - llvm::{self, r#type::pointer, LoadStoreOptions}, - memref, ods, + llvm::{self, LoadStoreOptions}, + memref, }, ir::{ attribute::{ @@ -135,93 +135,6 @@ pub fn compile( } } - { - // Add the builtin_costs global. - // We always add it because symbol look up otherwise can panic. - let region = Region::new(); - let location = Location::unknown(context); - let block = region.append_block(Block::new(&[])); - let value = block.append_op_result( - ods::llvm::mlir_zero(context, llvm::r#type::pointer(context, 0), location).into(), - )?; - block.append_operation(melior::dialect::llvm::r#return(Some(value), location)); - - module.body().append_operation({ - let mut op = ods::llvm::mlir_global( - context, - region, - TypeAttribute::new(llvm::r#type::pointer(context, 0)), - StringAttribute::new(context, "builtin_costs"), - Attribute::parse(context, "#llvm.linkage").unwrap(), - location, - ); - op.set_thread_local(Attribute::unit(context)); - - op.into() - }); - - module.body().append_operation({ - llvm::func( - context, - StringAttribute::new(context, "internal_set_builtin_costs"), - TypeAttribute::new(llvm::r#type::function( - llvm::r#type::void(context), - &[pointer(context, 0)], - false, - )), - { - let region = Region::new(); - - let entry = region.append_block(Block::new(&[(pointer(context, 0), location)])); - - let global = entry.append_op_result( - ods::llvm::mlir_addressof( - context, - pointer(context, 0), - FlatSymbolRefAttribute::new(context, "builtin_costs"), - location, - ) - .into(), - )?; - let thread_local_ptr = entry.append_op_result( - ods::llvm::intr_threadlocal_address( - context, - pointer(context, 0), - global, - location, - ) - .into(), - )?; - entry.store( - context, - location, - thread_local_ptr, - entry.argument(0)?.into(), - )?; - - entry.append_operation(llvm::r#return(None, location)); - - region - }, - &[ - ( - Identifier::new(context, "sym_visibility"), - StringAttribute::new(context, "public").into(), - ), - ( - Identifier::new(context, "linkage"), - Attribute::parse(context, "#llvm.linkage").unwrap(), - ), - ( - Identifier::new(context, "CConv"), - Attribute::parse(context, "#llvm.cconv").unwrap(), - ), - ], - location, - ) - }); - } - // Sierra programs have the following structure: // 1. Type declarations, one per line. // 2. Libfunc declarations, one per line. diff --git a/src/executor.rs b/src/executor.rs index 6625690cf..b6d70cd56 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -69,7 +69,7 @@ extern "C" { fn invoke_dynamic( registry: &ProgramRegistry, function_ptr: *const c_void, - builtin_costs_setter_ptr: extern "C" fn(*const u64), + set_builtin_costs_fnptr: extern "C" fn(*const u64), function_signature: &FunctionSignature, args: &[Value], gas: u128, @@ -144,9 +144,7 @@ fn invoke_dynamic( // Order matters, for the libfunc impl let builtin_costs: [u64; 7] = BuiltinCosts::default().into(); - - // set the builtin costs using the utility method to set the thread local - builtin_costs_setter_ptr(builtin_costs.as_ptr()); + set_builtin_costs_fnptr(builtin_costs.as_ptr()); // Generate argument list. let mut iter = args.iter(); diff --git a/src/executor/aot.rs b/src/executor/aot.rs index 8b1e903bf..e25cf504a 100644 --- a/src/executor/aot.rs +++ b/src/executor/aot.rs @@ -55,13 +55,17 @@ impl AotNativeExecutor { mut metadata, } = module; - let library_path = NamedTempFile::new().unwrap().into_temp_path(); + let library_path = NamedTempFile::new() + .unwrap() + .into_temp_path() + .keep() + .unwrap(); let object_data = crate::module_to_object(&module, opt_level).unwrap(); crate::object_to_shared_lib(&object_data, &library_path).unwrap(); Self { - library: unsafe { Library::new(library_path).unwrap() }, + library: unsafe { Library::new(&library_path).unwrap() }, registry, gas_metadata: metadata.remove().unwrap(), } @@ -78,10 +82,10 @@ impl AotNativeExecutor { .get_initial_available_gas(function_id, gas) .map_err(crate::error::Error::GasMetadataError)?; - let builtin_setter_ptr = unsafe { - std::mem::transmute::<*mut libc::c_void, extern "C" fn(*const u64)>( + let set_costs_builtin: extern "C" fn(*const u64) = unsafe { + std::mem::transmute( self.library - .get::(b"internal_set_builtin_costs")? + .get::(b"cairo_native__set_costs_builtin")? .into_raw() .into_raw(), ) @@ -90,7 +94,7 @@ impl AotNativeExecutor { super::invoke_dynamic( &self.registry, self.find_function_ptr(function_id), - builtin_setter_ptr, + set_costs_builtin, self.extract_signature(function_id), args, available_gas, @@ -110,10 +114,10 @@ impl AotNativeExecutor { .get_initial_available_gas(function_id, gas) .map_err(crate::error::Error::GasMetadataError)?; - let builtin_setter_ptr = unsafe { - std::mem::transmute::<*mut libc::c_void, extern "C" fn(*const u64)>( + let set_costs_builtin: extern "C" fn(*const u64) = unsafe { + std::mem::transmute( self.library - .get::(b"internal_set_builtin_costs")? + .get::(b"cairo_native__set_costs_builtin")? .into_raw() .into_raw(), ) @@ -122,7 +126,7 @@ impl AotNativeExecutor { super::invoke_dynamic( &self.registry, self.find_function_ptr(function_id), - builtin_setter_ptr, + set_costs_builtin, self.extract_signature(function_id), args, available_gas, @@ -142,10 +146,10 @@ impl AotNativeExecutor { .get_initial_available_gas(function_id, gas) .map_err(crate::error::Error::GasMetadataError)?; - let builtin_setter_ptr = unsafe { - std::mem::transmute::<*mut libc::c_void, extern "C" fn(*const u64)>( + let set_costs_builtin: extern "C" fn(*const u64) = unsafe { + std::mem::transmute( self.library - .get::(b"internal_set_builtin_costs")? + .get::(b"cairo_native__set_costs_builtin")? .into_raw() .into_raw(), ) @@ -154,7 +158,7 @@ impl AotNativeExecutor { ContractExecutionResult::from_execution_result(super::invoke_dynamic( &self.registry, self.find_function_ptr(function_id), - builtin_setter_ptr, + set_costs_builtin, self.extract_signature(function_id), &[Value::Struct { fields: vec![Value::Array( diff --git a/src/executor/contract.rs b/src/executor/contract.rs index ec11144b8..c4495ad30 100644 --- a/src/executor/contract.rs +++ b/src/executor/contract.rs @@ -302,15 +302,14 @@ impl AotContractExecutor { }; let function_ptr = self.find_function_ptr(&function_id, true)?; - let builtin_setter_ptr = unsafe { - self.library - .get::(b"internal_set_builtin_costs")? - }; - let builtin_costs = builtin_costs.unwrap_or_default(); let builtin_costs: [u64; 7] = builtin_costs.into(); // set the builtin costs using the utility method to set the thread local - builtin_setter_ptr(builtin_costs.as_ptr()); + let set_costs_builtin = unsafe { + self.library + .get::(b"cairo_native__set_costs_builtin")? + }; + set_costs_builtin(builtin_costs.as_ptr()); let initial_gas_cost = { let mut cost = 0; diff --git a/src/executor/jit.rs b/src/executor/jit.rs index 41a73115d..a2c9dd9c2 100644 --- a/src/executor/jit.rs +++ b/src/executor/jit.rs @@ -76,13 +76,13 @@ impl<'m> JitNativeExecutor<'m> { .get_initial_available_gas(function_id, gas) .map_err(crate::error::Error::GasMetadataError)?; - let builtin_setter_ptr: extern "C" fn(*const u64) = - unsafe { std::mem::transmute(self.engine.lookup("internal_set_builtin_costs")) }; + let set_builtin_costs_fnptr: extern "C" fn(*const u64) = + unsafe { std::mem::transmute(self.engine.lookup("cairo_native__set_costs_builtin")) }; super::invoke_dynamic( &self.registry, self.find_function_ptr(function_id), - builtin_setter_ptr, + set_builtin_costs_fnptr, self.extract_signature(function_id).unwrap(), args, available_gas, @@ -103,13 +103,13 @@ impl<'m> JitNativeExecutor<'m> { .get_initial_available_gas(function_id, gas) .map_err(crate::error::Error::GasMetadataError)?; - let builtin_setter_ptr: extern "C" fn(*const u64) = - unsafe { std::mem::transmute(self.engine.lookup("internal_set_builtin_costs")) }; + let set_builtin_costs_fnptr: extern "C" fn(*const u64) = + unsafe { std::mem::transmute(self.engine.lookup("cairo_native__set_costs_builtin")) }; super::invoke_dynamic( &self.registry, self.find_function_ptr(function_id), - builtin_setter_ptr, + set_builtin_costs_fnptr, self.extract_signature(function_id).unwrap(), args, available_gas, @@ -129,13 +129,13 @@ impl<'m> JitNativeExecutor<'m> { .get_initial_available_gas(function_id, gas) .map_err(crate::error::Error::GasMetadataError)?; - let builtin_setter_ptr: extern "C" fn(*const u64) = - unsafe { std::mem::transmute(self.engine.lookup("internal_set_builtin_costs")) }; + let set_builtin_costs_fnptr: extern "C" fn(*const u64) = + unsafe { std::mem::transmute(self.engine.lookup("cairo_native__set_costs_builtin")) }; ContractExecutionResult::from_execution_result(super::invoke_dynamic( &self.registry, self.find_function_ptr(function_id), - builtin_setter_ptr, + set_builtin_costs_fnptr, self.extract_signature(function_id).unwrap(), &[Value::Struct { fields: vec![Value::Array( diff --git a/src/ffi.rs b/src/ffi.rs index 0dbb8aa1d..1e8747621 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -290,10 +290,10 @@ pub fn object_to_shared_lib(object: &[u8], output_filename: &Path) -> Result<()> { let mut args: Vec> = vec![ "--hash-style=gnu".into(), - "--eh-frame-hdr".into(), "-shared".into(), "-L/lib/../lib64".into(), "-L/usr/lib/../lib64".into(), + "--no-strip-discarded".into(), ]; args.extend([ @@ -301,6 +301,7 @@ pub fn object_to_shared_lib(object: &[u8], output_filename: &Path) -> Result<()> Cow::from(output_path), "-lc".into(), Cow::from(file_path), + "--whole-archive".into(), // needed so `cairo_native__set_costs_builtin` is always available Cow::from(runtime_library_path), ]); diff --git a/src/libfuncs/gas.rs b/src/libfuncs/gas.rs index 0cf4f8c76..b5ff098e8 100644 --- a/src/libfuncs/gas.rs +++ b/src/libfuncs/gas.rs @@ -2,16 +2,15 @@ use super::LibfuncHelper; use crate::{ - error::Result, - metadata::{gas::GasCost, MetadataStorage}, - utils::{BlockExt, ProgramRegistryExt}, + error::{Error, Result}, + metadata::{gas::GasCost, runtime_bindings::RuntimeBindingsMeta, MetadataStorage}, + utils::BlockExt, }; use cairo_lang_sierra::{ extensions::{ core::{CoreLibfunc, CoreType}, gas::{CostTokenType, GasConcreteLibfunc}, lib_func::SignatureOnlyConcreteLibfunc, - ConcreteLibfunc, }, program_registry::ProgramRegistry, }; @@ -21,7 +20,7 @@ use melior::{ llvm::{self, r#type::pointer}, ods, }, - ir::{attribute::FlatSymbolRefAttribute, r#type::IntegerType, Block, Location}, + ir::{r#type::IntegerType, Block, Location}, Context, }; @@ -77,7 +76,7 @@ pub fn build_withdraw_gas<'ctx, 'this>( entry: &'this Block<'ctx>, location: Location<'ctx>, helper: &LibfuncHelper<'ctx, 'this>, - metadata: &MetadataStorage, + metadata: &mut MetadataStorage, _info: &SignatureOnlyConcreteLibfunc, ) -> Result<()> { let range_check = @@ -86,37 +85,21 @@ pub fn build_withdraw_gas<'ctx, 'this>( let gas_cost = metadata .get::() - .expect("builtin_withdraw_gas should always have a gas cost"); + .expect("builtin_withdraw_gas should always have a gas cost") + .clone(); let u128_type: melior::ir::Type = IntegerType::new(context, 128).into(); let u64_type: melior::ir::Type = IntegerType::new(context, 64).into(); - // Get the ptr to the global, holding a ptr to the list. - let builtin_ptr_ptr = entry.append_op_result( - ods::llvm::mlir_addressof( - context, - pointer(context, 0), - FlatSymbolRefAttribute::new(context, "builtin_costs"), - location, - ) - .into(), - )?; - let thread_local_builtin_ptr_ptr = entry.append_op_result( - ods::llvm::intr_threadlocal_address( - context, - pointer(context, 0), - builtin_ptr_ptr, - location, - ) - .into(), - )?; - - let builtin_ptr = entry.load( - context, - location, - thread_local_builtin_ptr_ptr, - pointer(context, 0), - )?; + let builtin_ptr = { + let runtime = metadata + .get_mut::() + .ok_or(Error::MissingMetadata)?; + runtime + .get_gas_builtin(context, helper, entry, location)? + .result(0)? + .into() + }; let mut final_gas_cost = entry.const_int_from_type(context, location, 0, u128_type)?; @@ -273,47 +256,23 @@ pub fn build_builtin_withdraw_gas<'ctx, 'this>( /// Generate MLIR operations for the `get_builtin_costs` libfunc. pub fn build_get_builtin_costs<'ctx, 'this>( context: &'ctx Context, - registry: &ProgramRegistry, + _registry: &ProgramRegistry, entry: &'this Block<'ctx>, location: Location<'ctx>, helper: &LibfuncHelper<'ctx, 'this>, metadata: &mut MetadataStorage, - info: &SignatureOnlyConcreteLibfunc, + _info: &SignatureOnlyConcreteLibfunc, ) -> Result<()> { - let builtin_costs_ty = registry.build_type( - context, - helper, - registry, - metadata, - &info.branch_signatures()[0].vars[0].ty, - )?; - // Get the ptr to the global, holding a ptr to the list. - let builtin_ptr_ptr = entry.append_op_result( - ods::llvm::mlir_addressof( - context, - pointer(context, 0), - FlatSymbolRefAttribute::new(context, "builtin_costs"), - location, - ) - .into(), - )?; - let thread_local_builtin_ptr_ptr = entry.append_op_result( - ods::llvm::intr_threadlocal_address( - context, - pointer(context, 0), - builtin_ptr_ptr, - location, - ) - .into(), - )?; - - let builtin_ptr = entry.load( - context, - location, - thread_local_builtin_ptr_ptr, - builtin_costs_ty, - )?; + let builtin_ptr = { + let runtime = metadata + .get_mut::() + .ok_or(Error::MissingMetadata)?; + runtime + .get_gas_builtin(context, helper, entry, location)? + .result(0)? + .into() + }; entry.append_operation(helper.br(0, &[builtin_ptr], location)); diff --git a/src/metadata/runtime_bindings.rs b/src/metadata/runtime_bindings.rs index 3ddbf0441..225b671c3 100644 --- a/src/metadata/runtime_bindings.rs +++ b/src/metadata/runtime_bindings.rs @@ -31,6 +31,7 @@ enum RuntimeBinding { DictGasRefund, DictDrop, DictDup, + GetGasBuiltin, DebugPrint, #[cfg(feature = "with-cheatcode")] VtableCheatcode, @@ -862,6 +863,49 @@ impl RuntimeBindingsMeta { ))) } + // Register if necessary, then invoke the `set_gas_builtin()` function. + #[allow(clippy::too_many_arguments)] + pub fn get_gas_builtin<'c, 'a>( + &mut self, + context: &'c Context, + module: &Module, + block: &'a Block<'c>, + location: Location<'c>, + ) -> Result> + where + 'c: 'a, + { + if self.active_map.insert(RuntimeBinding::GetGasBuiltin) { + module.body().append_operation(func::func( + context, + StringAttribute::new(context, "cairo_native__get_costs_builtin"), + TypeAttribute::new( + FunctionType::new(context, &[], &[llvm::r#type::pointer(context, 0)]).into(), + ), + Region::new(), + &[ + ( + Identifier::new(context, "sym_visibility"), + StringAttribute::new(context, "private").into(), + ), + ( + Identifier::new(context, "llvm.linkage"), + Attribute::parse(context, "#llvm.linkage").unwrap(), + ), + ], + Location::unknown(context), + )); + } + + Ok(block.append_operation(func::call( + context, + FlatSymbolRefAttribute::new(context, "cairo_native__get_costs_builtin"), + &[], + &[llvm::r#type::pointer(context, 0)], + location, + ))) + } + /// Register if necessary, then invoke the `vtable_cheatcode()` runtime function. /// /// Calls the cheatcode syscall with the given arguments. diff --git a/src/utils.rs b/src/utils.rs index 90a315860..0d0d30568 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -393,6 +393,18 @@ pub fn register_runtime_symbols(engine: &ExecutionEngine) { as *mut (), ); + engine.register_symbol( + "cairo_native__set_costs_builtin", + cairo_native_runtime::cairo_native__set_costs_builtin as *const fn(*const u64) -> () + as *mut (), + ); + + engine.register_symbol( + "cairo_native__get_costs_builtin", + cairo_native_runtime::cairo_native__get_costs_builtin as *const fn() -> *const u64 + as *mut (), + ); + #[cfg(feature = "with-cheatcode")] { engine.register_symbol( From 2bb59c9d6ee2d6dbed9f2212e333fcd69cd8cf84 Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Mon, 4 Nov 2024 08:56:55 +0100 Subject: [PATCH 09/31] fix --- src/ffi.rs | 1 - src/utils.rs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ffi.rs b/src/ffi.rs index 1e8747621..fdcf92cf2 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -293,7 +293,6 @@ pub fn object_to_shared_lib(object: &[u8], output_filename: &Path) -> Result<()> "-shared".into(), "-L/lib/../lib64".into(), "-L/usr/lib/../lib64".into(), - "--no-strip-discarded".into(), ]; args.extend([ diff --git a/src/utils.rs b/src/utils.rs index 0d0d30568..a2cfc77a3 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -271,7 +271,7 @@ pub fn create_engine( opt_level: OptLevel, ) -> ExecutionEngine { // Create the JIT engine. - let engine = ExecutionEngine::new(module, opt_level.into(), &[""], false); + let engine = ExecutionEngine::new(module, opt_level.into(), &[], false); #[cfg(feature = "with-runtime")] register_runtime_symbols(&engine); From 4a07cf4508273d064acfb98f2e6497d06bce5a1a Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Mon, 4 Nov 2024 09:00:27 +0100 Subject: [PATCH 10/31] upd ref ci --- .github/workflows/starknet-blocks.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/starknet-blocks.yml b/.github/workflows/starknet-blocks.yml index 1d336ed7a..036f204ca 100644 --- a/.github/workflows/starknet-blocks.yml +++ b/.github/workflows/starknet-blocks.yml @@ -74,7 +74,7 @@ jobs: uses: actions/checkout@v4 with: repository: lambdaclass/starknet-replay - ref: b46fcc79b839948636901d189a3c1e7d0832f831 + ref: 3950531b49799d1a020edd57b919b015ccd448f7 path: replay - name: Install Starknet Replay deps From 675a285e9cbf79399a6aba4b5ee159ac1e3543e6 Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Mon, 4 Nov 2024 09:08:26 +0100 Subject: [PATCH 11/31] upd replay --- .github/workflows/starknet-blocks.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/starknet-blocks.yml b/.github/workflows/starknet-blocks.yml index 036f204ca..acb333fe5 100644 --- a/.github/workflows/starknet-blocks.yml +++ b/.github/workflows/starknet-blocks.yml @@ -74,7 +74,7 @@ jobs: uses: actions/checkout@v4 with: repository: lambdaclass/starknet-replay - ref: 3950531b49799d1a020edd57b919b015ccd448f7 + ref: 47fa90bb2f1fda6e6a2c032719f897b2c0070e18 path: replay - name: Install Starknet Replay deps From fe4d4b89fd15e965c7c91f3e691eacb9372c9d94 Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Mon, 4 Nov 2024 09:30:48 +0100 Subject: [PATCH 12/31] fix macos --- src/ffi.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ffi.rs b/src/ffi.rs index fdcf92cf2..8bad224ff 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -281,6 +281,7 @@ pub fn object_to_shared_lib(object: &[u8], output_filename: &Path) -> Result<()> "-o".into(), Cow::from(output_path), "-lSystem".into(), + "--whole-archive".into(), // needed so `cairo_native__set_costs_builtin` is always available Cow::from(runtime_library_path), ]); From 1024bc6f1a6402d305fe40a7f01992eba4682594 Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Mon, 4 Nov 2024 10:06:58 +0100 Subject: [PATCH 13/31] try to fix macos --- Makefile | 1 + scripts/bench-hyperfine.sh | 42 ++++++-------------------------------- src/ffi.rs | 2 +- 3 files changed, 8 insertions(+), 37 deletions(-) diff --git a/Makefile b/Makefile index 217091874..6c6c75318 100644 --- a/Makefile +++ b/Makefile @@ -97,6 +97,7 @@ doc-open: check-llvm .PHONY: bench bench: needs-cairo2 runtime cargo b --release --bin cairo-native-run + cargo b --release --bin cairo-native-compile ./scripts/bench-hyperfine.sh .PHONY: bench-ci diff --git a/scripts/bench-hyperfine.sh b/scripts/bench-hyperfine.sh index 180120c79..eb11460cf 100755 --- a/scripts/bench-hyperfine.sh +++ b/scripts/bench-hyperfine.sh @@ -10,7 +10,7 @@ CAIRO_SRCS=$(find \ IFS=$'\n' read -rd '' -a CAIRO_SRCS <<<"$CAIRO_SRCS" CAIRO_RUN="$ROOT_DIR/cairo2/bin/cairo-run" -COMPILER_CLI="$ROOT_DIR/target/release/cairo-native-dump" +COMPILER_CLI="$ROOT_DIR/target/release/cairo-native-compile" JIT_CLI="$ROOT_DIR/target/release/cairo-native-run" OUTPUT_DIR="$ROOT_DIR/target/bench-outputs" @@ -43,38 +43,8 @@ run_bench() { "$COMPILER_CLI" \ "$base_path.cairo" \ - --output "$OUTPUT_DIR/$base_name.mlir" \ - >> /dev/stderr - - "$MLIR_DIR/bin/mlir-opt" \ - --canonicalize \ - --convert-scf-to-cf \ - --canonicalize \ - --cse \ - --expand-strided-metadata \ - --finalize-memref-to-llvm \ - --convert-func-to-llvm \ - --convert-index-to-llvm \ - --reconcile-unrealized-casts \ - "$OUTPUT_DIR/$base_name.mlir" \ - -o "$OUTPUT_DIR/$base_name.opt.mlir" \ - >> /dev/stderr - - "$MLIR_DIR/bin/mlir-translate" \ - --mlir-to-llvmir \ - "$OUTPUT_DIR/$base_name.opt.mlir" \ - -o "$OUTPUT_DIR/$base_name.ll" \ - >> /dev/stderr - - "$MLIR_DIR/bin/clang" \ - -O3 \ - -Wno-override-module \ - "$base_path.c" \ - "$OUTPUT_DIR/$base_name.ll" \ - -L "target/release" \ - -Wl,-rpath "$MLIR_DIR/lib" \ - -Wl,-rpath "target/release" \ - -o "$OUTPUT_DIR/$base_name" \ + --output-mlir "$OUTPUT_DIR/$base_name.mlir" \ + --output-library "$OUTPUT_DIR/$base_name.so" \ >> /dev/stderr "$MLIR_DIR/bin/clang" \ @@ -83,10 +53,10 @@ run_bench() { -mtune=native \ -Wno-override-module \ "$base_path.c" \ - "$OUTPUT_DIR/$base_name.ll" \ - -L "target/release" \ + -L "$OUTPUT_DIR/" \ -Wl,-rpath "$MLIR_DIR/lib" \ - -Wl,-rpath "target/release" \ + -Wl,-rpath "$OUTPUT_DIR/" \ + -l:"$OUTPUT_DIR/$base_name.so" \ -o "$OUTPUT_DIR/$base_name-march-native" \ >> /dev/stderr diff --git a/src/ffi.rs b/src/ffi.rs index 8bad224ff..4113bb8d7 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -281,7 +281,7 @@ pub fn object_to_shared_lib(object: &[u8], output_filename: &Path) -> Result<()> "-o".into(), Cow::from(output_path), "-lSystem".into(), - "--whole-archive".into(), // needed so `cairo_native__set_costs_builtin` is always available + "-force_load".into(), // needed so `cairo_native__set_costs_builtin` is always available Cow::from(runtime_library_path), ]); From 6d1603c48ff369efbef1b3f520b040fe172fceaf Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Mon, 4 Nov 2024 10:22:06 +0100 Subject: [PATCH 14/31] try to fix bench --- programs/benches/factorial_2M.c | 7 ++++--- programs/benches/fib_2M.c | 6 +++--- programs/benches/logistic_map.c | 6 +++--- scripts/bench-hyperfine.sh | 12 ++++++------ 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/programs/benches/factorial_2M.c b/programs/benches/factorial_2M.c index 9beefef5f..35733da7c 100644 --- a/programs/benches/factorial_2M.c +++ b/programs/benches/factorial_2M.c @@ -16,11 +16,12 @@ typedef struct factorial_return_values } result; } factorial_return_values_t; -extern uint64_t* builtin_costs; - static void run_bench(factorial_return_values_t*, uint64_t) __attribute__((weakref("_mlir_ciface_factorial_2M::factorial_2M::main(f1)"))); +static void cairo_native__set_costs_builtin(uint64_t*) +__attribute__((weakref("cairo_native__set_costs_builtin)"))); + int main() { @@ -28,7 +29,7 @@ int main() uint64_t BuiltinCosts[7] = {1, 4050, 583, 4085, 491, 230, 604}; - builtin_costs = &BuiltinCosts[0]; + cairo_native__set_costs_builtin(&BuiltinCosts[0]); run_bench(&return_values, 0); assert(return_values.result.discriminant == 0); diff --git a/programs/benches/fib_2M.c b/programs/benches/fib_2M.c index 72a420a86..6a3583e30 100644 --- a/programs/benches/fib_2M.c +++ b/programs/benches/fib_2M.c @@ -16,17 +16,17 @@ typedef struct fib_return_values } result; } fib_return_values_t; -extern uint64_t* builtin_costs; - static void run_bench(fib_return_values_t *, uint64_t) __attribute__((weakref("_mlir_ciface_fib_2M::fib_2M::main(f1)"))); +static void cairo_native__set_costs_builtin(uint64_t*) +__attribute__((weakref("cairo_native__set_costs_builtin)"))); int main() { uint64_t BuiltinCosts[7] = {1, 4050, 583, 4085, 491, 230, 604}; - builtin_costs = &BuiltinCosts[0]; + cairo_native__set_costs_builtin(&BuiltinCosts[0]); fib_return_values_t return_values; diff --git a/programs/benches/logistic_map.c b/programs/benches/logistic_map.c index 483def4c4..af178fe1f 100644 --- a/programs/benches/logistic_map.c +++ b/programs/benches/logistic_map.c @@ -16,17 +16,17 @@ typedef struct map_return_values } result; } map_return_values_t; -extern uint64_t* builtin_costs; - static void run_bench(map_return_values_t *, uint64_t) __attribute__((weakref("_mlir_ciface_logistic_map::logistic_map::main(f2)"))); +static void cairo_native__set_costs_builtin(uint64_t*) +__attribute__((weakref("cairo_native__set_costs_builtin)"))); int main() { uint64_t BuiltinCosts[7] = {1, 4050, 583, 4085, 491, 230, 604}; - builtin_costs = &BuiltinCosts[0]; + cairo_native__set_costs_builtin(&BuiltinCosts[0]); map_return_values_t return_values; diff --git a/scripts/bench-hyperfine.sh b/scripts/bench-hyperfine.sh index eb11460cf..d614908d9 100755 --- a/scripts/bench-hyperfine.sh +++ b/scripts/bench-hyperfine.sh @@ -42,9 +42,9 @@ run_bench() { base_name=$(basename $base_path) "$COMPILER_CLI" \ - "$base_path.cairo" \ - --output-mlir "$OUTPUT_DIR/$base_name.mlir" \ - --output-library "$OUTPUT_DIR/$base_name.so" \ + -s "$base_path.cairo" \ + "$OUTPUT_DIR/$base_name.mlir" \ + "$OUTPUT_DIR/lib$base_name.so" \ >> /dev/stderr "$MLIR_DIR/bin/clang" \ @@ -55,8 +55,9 @@ run_bench() { "$base_path.c" \ -L "$OUTPUT_DIR/" \ -Wl,-rpath "$MLIR_DIR/lib" \ - -Wl,-rpath "$OUTPUT_DIR/" \ - -l:"$OUTPUT_DIR/$base_name.so" \ + -Wl,-rpath "$OUTPUT_DIR" \ + -lm \ + -l"$base_name" \ -o "$OUTPUT_DIR/$base_name-march-native" \ >> /dev/stderr @@ -67,7 +68,6 @@ run_bench() { -n "Cairo-vm (Rust, Cairo 1)" "$CAIRO_RUN --available-gas 18446744073709551615 -s $base_path.cairo" \ -n "cairo-native (embedded AOT)" "$JIT_CLI --run-mode=aot -s $base_path.cairo --opt-level 3 --available-gas 18446744073709551615 " \ -n "cairo-native (embedded JIT using LLVM's ORC Engine)" "$JIT_CLI --run-mode=jit -s $base_path.cairo --opt-level 3 --available-gas 18446744073709551615 " \ - -n "cairo-native (standalone AOT)" "$OUTPUT_DIR/$base_name" \ -n "cairo-native (standalone AOT with -march=native)" "$OUTPUT_DIR/$base_name-march-native" \ >> /dev/stderr } From 07ac00cbc717c56aa5c5ca01ccc519eaa2478f16 Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Mon, 4 Nov 2024 10:34:30 +0100 Subject: [PATCH 15/31] fix --- programs/benches/factorial_2M.c | 2 +- programs/benches/fib_2M.c | 2 +- programs/benches/logistic_map.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/programs/benches/factorial_2M.c b/programs/benches/factorial_2M.c index 35733da7c..6f5b36c3c 100644 --- a/programs/benches/factorial_2M.c +++ b/programs/benches/factorial_2M.c @@ -20,7 +20,7 @@ static void run_bench(factorial_return_values_t*, uint64_t) __attribute__((weakref("_mlir_ciface_factorial_2M::factorial_2M::main(f1)"))); static void cairo_native__set_costs_builtin(uint64_t*) -__attribute__((weakref("cairo_native__set_costs_builtin)"))); +__attribute__((weakref("cairo_native__set_costs_builtin"))); int main() diff --git a/programs/benches/fib_2M.c b/programs/benches/fib_2M.c index 6a3583e30..36e49166e 100644 --- a/programs/benches/fib_2M.c +++ b/programs/benches/fib_2M.c @@ -20,7 +20,7 @@ static void run_bench(fib_return_values_t *, uint64_t) __attribute__((weakref("_mlir_ciface_fib_2M::fib_2M::main(f1)"))); static void cairo_native__set_costs_builtin(uint64_t*) -__attribute__((weakref("cairo_native__set_costs_builtin)"))); +__attribute__((weakref("cairo_native__set_costs_builtin"))); int main() { diff --git a/programs/benches/logistic_map.c b/programs/benches/logistic_map.c index af178fe1f..2d7bd2af5 100644 --- a/programs/benches/logistic_map.c +++ b/programs/benches/logistic_map.c @@ -20,7 +20,7 @@ static void run_bench(map_return_values_t *, uint64_t) __attribute__((weakref("_mlir_ciface_logistic_map::logistic_map::main(f2)"))); static void cairo_native__set_costs_builtin(uint64_t*) -__attribute__((weakref("cairo_native__set_costs_builtin)"))); +__attribute__((weakref("cairo_native__set_costs_builtin"))); int main() { From d2d8ef04fa14fb5176eb871d7c28cf11268fcdae Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Mon, 4 Nov 2024 13:15:27 +0100 Subject: [PATCH 16/31] try to fix bench ci --- .github/workflows/bench-hyperfine.yml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/bench-hyperfine.yml b/.github/workflows/bench-hyperfine.yml index 02a123f3d..42f5efaff 100644 --- a/.github/workflows/bench-hyperfine.yml +++ b/.github/workflows/bench-hyperfine.yml @@ -58,15 +58,11 @@ jobs: - name: Install hyperfine uses: taiki-e/install-action@v2 with: - tool: hyperfine@1.16 + tool: hyperfine@1.18 - name: Install deps run: make deps - - name: Build project - run: make build - - name: Build runtime subproject - run: make runtime-ci - name: Run benchmarks - run: ./scripts/bench-hyperfine.sh programs/benches/*.cairo + run: make bench - name: Create markdown file run: bash .github/scripts/merge-benches.sh From 939bb8756a37ce1941ead9f89d272f6834f5eff3 Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Mon, 4 Nov 2024 13:22:05 +0100 Subject: [PATCH 17/31] save space --- .github/workflows/starknet-blocks.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.github/workflows/starknet-blocks.yml b/.github/workflows/starknet-blocks.yml index acb333fe5..5df15d9c9 100644 --- a/.github/workflows/starknet-blocks.yml +++ b/.github/workflows/starknet-blocks.yml @@ -116,6 +116,22 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Check and free hdd space left + if: ${{ matrix.runner == 'native' }} + run: | + sudo apt-get update + sudo apt-get remove -y '^llvm-.*' + sudo apt-get remove -y 'php.*' + sudo apt-get remove -y '^dotnet-.*' + sudo apt-get remove -y '^temurin-.*' + sudo apt-get remove -y azure-cli microsoft-edge-stable google-chrome-stable firefox mono-devel + sudo apt-get autoremove -y + sudo apt-get clean + echo "Removing large directories" + # deleting 15GB + sudo rm -rf /usr/share/dotnet/ + sudo rm -rf /usr/local/lib/android + - name: Fetch Native dumps uses: actions/download-artifact@v4 with: From 6b0ead120697946af37bfa9356111da1e2eb26f1 Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Tue, 5 Nov 2024 14:05:34 +0100 Subject: [PATCH 18/31] upd rev --- .github/workflows/starknet-blocks.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/starknet-blocks.yml b/.github/workflows/starknet-blocks.yml index 5df15d9c9..e373a6e51 100644 --- a/.github/workflows/starknet-blocks.yml +++ b/.github/workflows/starknet-blocks.yml @@ -74,7 +74,7 @@ jobs: uses: actions/checkout@v4 with: repository: lambdaclass/starknet-replay - ref: 47fa90bb2f1fda6e6a2c032719f897b2c0070e18 + ref: ae8b771795f3504101574ae8876fa80e3eb285d8 path: replay - name: Install Starknet Replay deps From 0845cb053e0c75d850d11afbbeff0765f80b5c03 Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Tue, 5 Nov 2024 14:51:12 +0100 Subject: [PATCH 19/31] try to fix broken pipe --- scripts/diff-check.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/diff-check.sh b/scripts/diff-check.sh index 5350934be..56aa8ce2b 100755 --- a/scripts/diff-check.sh +++ b/scripts/diff-check.sh @@ -18,8 +18,8 @@ for vm_dump in state_dumps/vm/*/*.json; do base=$(basename "$vm_dump") if ! cmp -s \ - <(sed '/"reverted": /d' "$native_dump") \ - <(sed '/"reverted": /d' "$vm_dump") + <(sed '/"reverted": /d' "$native_dump" 2>/dev/null) \ + <(sed '/"reverted": /d' "$vm_dump" 2>/dev/null) then echo "NATIVE DIFFING IN TX: $native_dump" diffing=1 From 2a6606f58842b096a4f8f21cb2ee81143ebc2403 Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Tue, 5 Nov 2024 15:22:27 +0100 Subject: [PATCH 20/31] try to fix bench on ci --- programs/benches/factorial_2M.c | 5 +++-- programs/benches/fib_2M.c | 5 +++-- programs/benches/logistic_map.c | 5 +++-- scripts/diff-check.sh | 2 -- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/programs/benches/factorial_2M.c b/programs/benches/factorial_2M.c index 6f5b36c3c..f07ff4686 100644 --- a/programs/benches/factorial_2M.c +++ b/programs/benches/factorial_2M.c @@ -10,7 +10,8 @@ typedef struct factorial_return_values uint8_t discriminant; struct { void* ptr; - uint32_t len; + uint32_t start; + uint32_t end; uint32_t cap; } err; } result; @@ -32,7 +33,7 @@ int main() cairo_native__set_costs_builtin(&BuiltinCosts[0]); run_bench(&return_values, 0); - assert(return_values.result.discriminant == 0); + assert((return_values.result.discriminant & 0x1) == 0); return 0; } diff --git a/programs/benches/fib_2M.c b/programs/benches/fib_2M.c index 36e49166e..0fd4404ad 100644 --- a/programs/benches/fib_2M.c +++ b/programs/benches/fib_2M.c @@ -10,7 +10,8 @@ typedef struct fib_return_values uint8_t discriminant; struct { void *ptr; - uint32_t len; + uint32_t start; + uint32_t end; uint32_t cap; } err; } result; @@ -31,7 +32,7 @@ int main() fib_return_values_t return_values; run_bench(&return_values, 0); - assert(return_values.result.discriminant == 0); + assert((return_values.result.discriminant & 0x1) == 0); return 0; } diff --git a/programs/benches/logistic_map.c b/programs/benches/logistic_map.c index 2d7bd2af5..12493d39e 100644 --- a/programs/benches/logistic_map.c +++ b/programs/benches/logistic_map.c @@ -10,7 +10,8 @@ typedef struct map_return_values uint8_t discriminant; struct { void *ptr; - uint32_t len; + uint32_t start; + uint32_t end; uint32_t cap; } err; } result; @@ -31,7 +32,7 @@ int main() map_return_values_t return_values; run_bench(&return_values, 0); - assert(return_values.result.discriminant == 0); + assert((return_values.result.discriminant & 0x1) == 0); return 0; } diff --git a/scripts/diff-check.sh b/scripts/diff-check.sh index 56aa8ce2b..752394936 100755 --- a/scripts/diff-check.sh +++ b/scripts/diff-check.sh @@ -15,8 +15,6 @@ for vm_dump in state_dumps/vm/*/*.json; do continue fi - base=$(basename "$vm_dump") - if ! cmp -s \ <(sed '/"reverted": /d' "$native_dump" 2>/dev/null) \ <(sed '/"reverted": /d' "$vm_dump" 2>/dev/null) From 18fa33ad8e3f12d9fef9cc9685274d2e0b91c7e8 Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Tue, 5 Nov 2024 15:31:51 +0100 Subject: [PATCH 21/31] remove all features --- .github/workflows/starknet-blocks.yml | 2 +- scripts/bench-hyperfine.sh | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/starknet-blocks.yml b/.github/workflows/starknet-blocks.yml index e373a6e51..4e16369c8 100644 --- a/.github/workflows/starknet-blocks.yml +++ b/.github/workflows/starknet-blocks.yml @@ -62,7 +62,7 @@ jobs: run: make deps - name: Build Cairo Native project if: ${{ matrix.runner == 'native' }} - run: cargo b --release --all-features + run: cargo b --release - name: Build runtime if: ${{ matrix.runner == 'native' }} run: | diff --git a/scripts/bench-hyperfine.sh b/scripts/bench-hyperfine.sh index d614908d9..bad57a13a 100755 --- a/scripts/bench-hyperfine.sh +++ b/scripts/bench-hyperfine.sh @@ -49,6 +49,7 @@ run_bench() { "$MLIR_DIR/bin/clang" \ -O3 \ + -g \ -march=native \ -mtune=native \ -Wno-override-module \ From adcec653b9c63b3c5440605d3e48a4776ac4b4a7 Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Tue, 5 Nov 2024 15:38:43 +0100 Subject: [PATCH 22/31] add cache key --- .github/workflows/starknet-blocks.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/starknet-blocks.yml b/.github/workflows/starknet-blocks.yml index 4e16369c8..13930362e 100644 --- a/.github/workflows/starknet-blocks.yml +++ b/.github/workflows/starknet-blocks.yml @@ -26,6 +26,8 @@ jobs: with: components: clippy - uses: Swatinem/rust-cache@v2 + with: + key: "ref-ae8b771795f3504101574ae8876fa80e3eb285d8" - name: Check and free hdd space left if: ${{ matrix.runner == 'native' }} From 40f1acc5c10687ed6c43a0a7dbd09c581ca10ec6 Mon Sep 17 00:00:00 2001 From: FrancoGiachetta Date: Tue, 5 Nov 2024 16:23:14 -0300 Subject: [PATCH 23/31] update replay rev --- .github/workflows/starknet-blocks.yml | 4 +- Cargo.lock | 219 +++++++++++++------------- 2 files changed, 113 insertions(+), 110 deletions(-) diff --git a/.github/workflows/starknet-blocks.yml b/.github/workflows/starknet-blocks.yml index 13930362e..441d87ea3 100644 --- a/.github/workflows/starknet-blocks.yml +++ b/.github/workflows/starknet-blocks.yml @@ -27,7 +27,7 @@ jobs: components: clippy - uses: Swatinem/rust-cache@v2 with: - key: "ref-ae8b771795f3504101574ae8876fa80e3eb285d8" + key: "ref-0dfc3d9a8c85a2d6ee53e431bd8a21e2d6839a32" - name: Check and free hdd space left if: ${{ matrix.runner == 'native' }} @@ -76,7 +76,7 @@ jobs: uses: actions/checkout@v4 with: repository: lambdaclass/starknet-replay - ref: ae8b771795f3504101574ae8876fa80e3eb285d8 + ref: 0dfc3d9a8c85a2d6ee53e431bd8a21e2d6839a32 path: replay - name: Install Starknet Replay deps diff --git a/Cargo.lock b/Cargo.lock index 54aafac03..9bf27accd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -54,9 +54,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" -version = "0.6.17" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -69,9 +69,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8365de52b16c035ff4fcafe0092ba9390540e3e352870ac09933bebcaa2c8c56" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" @@ -103,9 +103,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.91" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c042108f3ed77fd83760a5fd79b53be043192bb3b9dba91d8c574c0ada7850c8" +checksum = "74f37166d7d48a0284b99dd824694c26119c700b53bf0d1540cdb147dbdaaf13" [[package]] name = "aquamarine" @@ -118,7 +118,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -134,7 +134,7 @@ dependencies = [ "derivative", "hashbrown 0.13.2", "itertools 0.10.5", - "num-traits 0.2.19", + "num-traits", "zeroize", ] @@ -152,7 +152,7 @@ dependencies = [ "digest", "itertools 0.10.5", "num-bigint", - "num-traits 0.2.19", + "num-traits", "paste", "rustc_version", "zeroize", @@ -175,7 +175,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" dependencies = [ "num-bigint", - "num-traits 0.2.19", + "num-traits", "proc-macro2", "quote", "syn 1.0.109", @@ -245,7 +245,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" dependencies = [ - "num-traits 0.2.19", + "num-traits", "rand", ] @@ -310,7 +310,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.85", + "syn 2.0.87", "which", ] @@ -331,7 +331,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -434,7 +434,7 @@ dependencies = [ "cairo-lang-utils", "indoc", "num-bigint", - "num-traits 0.2.19", + "num-traits", "parity-scale-codec", "serde", ] @@ -568,7 +568,7 @@ dependencies = [ "itertools 0.12.1", "log", "num-bigint", - "num-traits 0.2.19", + "num-traits", "rust-analyzer-salsa", "smol_str", ] @@ -587,7 +587,7 @@ dependencies = [ "colored", "itertools 0.12.1", "num-bigint", - "num-traits 0.2.19", + "num-traits", "rust-analyzer-salsa", "smol_str", "unescaper", @@ -620,7 +620,7 @@ checksum = "d72f17373740f242d6995e896b9195c2cedff7e8b14e496afdd16b405039d1fb" dependencies = [ "cairo-lang-debug", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -660,7 +660,7 @@ dependencies = [ "keccak", "num-bigint", "num-integer", - "num-traits 0.2.19", + "num-traits", "rand", "sha2", "smol_str", @@ -688,7 +688,7 @@ dependencies = [ "indoc", "itertools 0.12.1", "num-bigint", - "num-traits 0.2.19", + "num-traits", "rust-analyzer-salsa", "smol_str", "toml", @@ -710,7 +710,7 @@ dependencies = [ "lalrpop-util", "num-bigint", "num-integer", - "num-traits 0.2.19", + "num-traits", "regex", "rust-analyzer-salsa", "serde", @@ -733,7 +733,7 @@ dependencies = [ "cairo-lang-utils", "itertools 0.12.1", "num-bigint", - "num-traits 0.2.19", + "num-traits", "thiserror", ] @@ -749,7 +749,7 @@ dependencies = [ "cairo-lang-utils", "itertools 0.12.1", "num-bigint", - "num-traits 0.2.19", + "num-traits", "thiserror", ] @@ -770,7 +770,7 @@ dependencies = [ "cairo-lang-syntax", "cairo-lang-utils", "itertools 0.12.1", - "num-traits 0.2.19", + "num-traits", "rust-analyzer-salsa", "serde", "serde_json", @@ -793,7 +793,7 @@ dependencies = [ "indoc", "itertools 0.12.1", "num-bigint", - "num-traits 0.2.19", + "num-traits", "starknet-types-core", "thiserror", ] @@ -852,7 +852,7 @@ dependencies = [ "itertools 0.12.1", "num-bigint", "num-integer", - "num-traits 0.2.19", + "num-traits", "serde", "serde_json", "sha3", @@ -871,7 +871,7 @@ dependencies = [ "cairo-lang-filesystem", "cairo-lang-utils", "num-bigint", - "num-traits 0.2.19", + "num-traits", "rust-analyzer-salsa", "smol_str", "unescaper", @@ -909,7 +909,7 @@ dependencies = [ "indoc", "itertools 0.12.1", "num-bigint", - "num-traits 0.2.19", + "num-traits", "serde", "starknet-types-core", ] @@ -937,7 +937,7 @@ dependencies = [ "indexmap 2.6.0", "itertools 0.12.1", "num-bigint", - "num-traits 0.2.19", + "num-traits", "schemars", "serde", ] @@ -984,7 +984,7 @@ dependencies = [ "mlir-sys", "num-bigint", "num-integer", - "num-traits 0.2.19", + "num-traits", "pretty_assertions_sorted", "proptest", "rayon", @@ -1012,7 +1012,7 @@ dependencies = [ "cairo-lang-sierra-gas", "itertools 0.13.0", "lazy_static", - "num-traits 0.2.19", + "num-traits", "rand", "starknet-curve 0.5.1", "starknet-types-core", @@ -1041,7 +1041,7 @@ dependencies = [ "num-bigint", "num-integer", "num-prime", - "num-traits 0.2.19", + "num-traits", "rand", "rust_decimal", "serde", @@ -1081,9 +1081,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.1.31" +version = "1.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" +checksum = "0f57c4b4da2a9d619dd035f27316d7a426305b75be93d09e92f2b9229c34feaf" dependencies = [ "jobserver", "libc", @@ -1184,7 +1184,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -1311,7 +1311,7 @@ dependencies = [ "criterion-plot", "is-terminal", "itertools 0.10.5", - "num-traits 0.2.19", + "num-traits", "once_cell", "oorandom", "plotters", @@ -1407,7 +1407,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -1418,7 +1418,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -1485,7 +1485,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -1495,7 +1495,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -1566,7 +1566,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -1613,7 +1613,7 @@ checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -1728,7 +1728,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -1786,7 +1786,7 @@ checksum = "553630feadf7b76442b0849fd25fdf89b860d933623aec9693fed19af0400c78" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -1833,12 +1833,12 @@ dependencies = [ [[package]] name = "good_lp" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3198bd13dea84c76a64621d6ee8ee26a4960a9a0d538eca95ca8f1320a469ac9" +checksum = "5b1668836f82863fed48defee60296cde17ee0beffa7b9be29dc2496747bafb4" dependencies = [ "fnv", - "minilp", + "microlp", ] [[package]] @@ -1879,9 +1879,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" +checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" dependencies = [ "allocator-api2", "equivalent", @@ -2021,7 +2021,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.15.0", + "hashbrown 0.15.1", "serde", ] @@ -2291,7 +2291,7 @@ version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown 0.15.0", + "hashbrown 0.15.1", ] [[package]] @@ -2305,10 +2305,11 @@ dependencies = [ [[package]] name = "matrixmultiply" -version = "0.2.4" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "916806ba0031cd542105d916a97c8572e1fa6dd79c9c51e7eb43a09ec2dd84c1" +checksum = "9380b911e3e96d10c1f415da0876389aaf1b56759054eeb0de7df940c456ba1a" dependencies = [ + "autocfg", "rawpointer", ] @@ -2336,7 +2337,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.85", + "syn 2.0.87", "tblgen-alt", "unindent", ] @@ -2348,10 +2349,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] -name = "minilp" -version = "0.2.2" +name = "microlp" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82a7750a9e5076c660b7bec5e6457b4dbff402b9863c8d112891434e18fd5385" +checksum = "4be6fbd22ab75d94d6e4419c2225a62ae22410c9ae1ecb4d743a1df906a55ca4" dependencies = [ "log", "sprs", @@ -2383,14 +2384,16 @@ dependencies = [ [[package]] name = "ndarray" -version = "0.13.1" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac06db03ec2f46ee0ecdca1a1c34a99c0d188a0d83439b84bf0cb4b386e4ab09" +checksum = "882ed72dce9365842bf196bdeedf5055305f11fc8c03dee7bb0194a6cad34841" dependencies = [ "matrixmultiply", "num-complex", "num-integer", - "num-traits 0.2.19", + "num-traits", + "portable-atomic", + "portable-atomic-util", "rawpointer", ] @@ -2427,19 +2430,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ "num-integer", - "num-traits 0.2.19", + "num-traits", "rand", "serde", ] [[package]] name = "num-complex" -version = "0.2.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ - "autocfg", - "num-traits 0.2.19", + "num-traits", ] [[package]] @@ -2454,7 +2456,7 @@ version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "num-traits 0.2.19", + "num-traits", ] [[package]] @@ -2465,7 +2467,7 @@ checksum = "64a5fe11d4135c3bcdf3a95b18b194afa9608a5f6ff034f5d857bc9a27fb0119" dependencies = [ "num-bigint", "num-integer", - "num-traits 0.2.19", + "num-traits", ] [[package]] @@ -2480,19 +2482,10 @@ dependencies = [ "num-bigint", "num-integer", "num-modular", - "num-traits 0.2.19", + "num-traits", "rand", ] -[[package]] -name = "num-traits" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" -dependencies = [ - "num-traits 0.2.19", -] - [[package]] name = "num-traits" version = "0.2.19" @@ -2527,7 +2520,7 @@ version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c" dependencies = [ - "num-traits 0.2.19", + "num-traits", ] [[package]] @@ -2669,7 +2662,7 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" dependencies = [ - "num-traits 0.2.19", + "num-traits", "plotters-backend", "plotters-svg", "wasm-bindgen", @@ -2697,6 +2690,15 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" +[[package]] +name = "portable-atomic-util" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90a7d5beecc52a491b54d6dd05c7a45ba1801666a5baad9fdbfc6fef8d2d206c" +dependencies = [ + "portable-atomic", +] + [[package]] name = "powerfmt" version = "0.2.0" @@ -2745,7 +2747,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" dependencies = [ "proc-macro2", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -2800,7 +2802,7 @@ dependencies = [ "bit-vec", "bitflags", "lazy_static", - "num-traits 0.2.19", + "num-traits", "rand", "rand_chacha", "rand_xorshift", @@ -3008,7 +3010,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn 2.0.85", + "syn 2.0.87", "unicode-ident", ] @@ -3038,7 +3040,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -3048,7 +3050,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b082d80e3e3cc52b2ed634388d436fe1f4de6af5786cc2de9ba9737527bdf555" dependencies = [ "arrayvec", - "num-traits 0.2.19", + "num-traits", ] [[package]] @@ -3068,9 +3070,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.38" +version = "0.38.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a" +checksum = "375116bee2be9ed569afe2154ea6a99dfdffd257f533f187498c2a8f5feaf4ee" dependencies = [ "bitflags", "errno", @@ -3164,7 +3166,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -3199,7 +3201,7 @@ checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -3210,7 +3212,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -3329,13 +3331,14 @@ checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "sprs" -version = "0.7.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec63571489873d4506683915840eeb1bb16b3198ee4894cc6f2fe3013d505e56" +checksum = "704ef26d974e8a452313ed629828cd9d4e4fa34667ca1ad9d6b1fffa43c6e166" dependencies = [ "ndarray", "num-complex", - "num-traits 0.1.43", + "num-traits", + "smallvec", ] [[package]] @@ -3355,7 +3358,7 @@ dependencies = [ "hmac", "num-bigint", "num-integer", - "num-traits 0.2.19", + "num-traits", "rfc6979", "sha2", "starknet-crypto-codegen", @@ -3372,7 +3375,7 @@ checksum = "bbc159a1934c7be9761c237333a57febe060ace2bc9e3b337a59a37af206d19f" dependencies = [ "starknet-curve 0.4.2", "starknet-ff", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -3416,7 +3419,7 @@ dependencies = [ "lazy_static", "num-bigint", "num-integer", - "num-traits 0.2.19", + "num-traits", "serde", ] @@ -3464,9 +3467,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.85" +version = "2.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" dependencies = [ "proc-macro2", "quote", @@ -3533,7 +3536,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -3544,28 +3547,28 @@ checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", "test-case-core", ] [[package]] name = "thiserror" -version = "1.0.65" +version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d11abd9594d9b38965ef50805c5e469ca9cc6f197f883f717e0269a3057b3d5" +checksum = "02dd99dc800bbb97186339685293e1cc5d9df1f8fae2d0aecd9ff1c77efea892" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.65" +version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae71770322cbd277e69d762a16c444af02aa0575ac0d174f0b9562d3b37f8602" +checksum = "a7c61ec9a6f64d2793d8a45faba21efbe3ced62a886d44c36a009b2b519b4c7e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -3704,7 +3707,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -3918,7 +3921,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", "wasm-bindgen-shared", ] @@ -3940,7 +3943,7 @@ checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4209,7 +4212,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -4229,7 +4232,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] From fce71429a873f4129abb2048976af738e8e69482 Mon Sep 17 00:00:00 2001 From: FrancoGiachetta Date: Tue, 5 Nov 2024 16:59:59 -0300 Subject: [PATCH 24/31] fix cargo.lock --- .github/workflows/starknet-blocks.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/starknet-blocks.yml b/.github/workflows/starknet-blocks.yml index 13930362e..441d87ea3 100644 --- a/.github/workflows/starknet-blocks.yml +++ b/.github/workflows/starknet-blocks.yml @@ -27,7 +27,7 @@ jobs: components: clippy - uses: Swatinem/rust-cache@v2 with: - key: "ref-ae8b771795f3504101574ae8876fa80e3eb285d8" + key: "ref-0dfc3d9a8c85a2d6ee53e431bd8a21e2d6839a32" - name: Check and free hdd space left if: ${{ matrix.runner == 'native' }} @@ -76,7 +76,7 @@ jobs: uses: actions/checkout@v4 with: repository: lambdaclass/starknet-replay - ref: ae8b771795f3504101574ae8876fa80e3eb285d8 + ref: 0dfc3d9a8c85a2d6ee53e431bd8a21e2d6839a32 path: replay - name: Install Starknet Replay deps From ad6c2ce4c05b4e61f081e6915df26fb670e7a120 Mon Sep 17 00:00:00 2001 From: FrancoGiachetta Date: Tue, 5 Nov 2024 17:02:44 -0300 Subject: [PATCH 25/31] Revert "update replay rev" This reverts commit 40f1acc5c10687ed6c43a0a7dbd09c581ca10ec6. --- .github/workflows/starknet-blocks.yml | 4 +- Cargo.lock | 219 +++++++++++++------------- 2 files changed, 110 insertions(+), 113 deletions(-) diff --git a/.github/workflows/starknet-blocks.yml b/.github/workflows/starknet-blocks.yml index 441d87ea3..13930362e 100644 --- a/.github/workflows/starknet-blocks.yml +++ b/.github/workflows/starknet-blocks.yml @@ -27,7 +27,7 @@ jobs: components: clippy - uses: Swatinem/rust-cache@v2 with: - key: "ref-0dfc3d9a8c85a2d6ee53e431bd8a21e2d6839a32" + key: "ref-ae8b771795f3504101574ae8876fa80e3eb285d8" - name: Check and free hdd space left if: ${{ matrix.runner == 'native' }} @@ -76,7 +76,7 @@ jobs: uses: actions/checkout@v4 with: repository: lambdaclass/starknet-replay - ref: 0dfc3d9a8c85a2d6ee53e431bd8a21e2d6839a32 + ref: ae8b771795f3504101574ae8876fa80e3eb285d8 path: replay - name: Install Starknet Replay deps diff --git a/Cargo.lock b/Cargo.lock index 9bf27accd..54aafac03 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -54,9 +54,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" -version = "0.6.18" +version = "0.6.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338" dependencies = [ "anstyle", "anstyle-parse", @@ -69,9 +69,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.10" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" +checksum = "8365de52b16c035ff4fcafe0092ba9390540e3e352870ac09933bebcaa2c8c56" [[package]] name = "anstyle-parse" @@ -103,9 +103,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.92" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74f37166d7d48a0284b99dd824694c26119c700b53bf0d1540cdb147dbdaaf13" +checksum = "c042108f3ed77fd83760a5fd79b53be043192bb3b9dba91d8c574c0ada7850c8" [[package]] name = "aquamarine" @@ -118,7 +118,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.85", ] [[package]] @@ -134,7 +134,7 @@ dependencies = [ "derivative", "hashbrown 0.13.2", "itertools 0.10.5", - "num-traits", + "num-traits 0.2.19", "zeroize", ] @@ -152,7 +152,7 @@ dependencies = [ "digest", "itertools 0.10.5", "num-bigint", - "num-traits", + "num-traits 0.2.19", "paste", "rustc_version", "zeroize", @@ -175,7 +175,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" dependencies = [ "num-bigint", - "num-traits", + "num-traits 0.2.19", "proc-macro2", "quote", "syn 1.0.109", @@ -245,7 +245,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" dependencies = [ - "num-traits", + "num-traits 0.2.19", "rand", ] @@ -310,7 +310,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.87", + "syn 2.0.85", "which", ] @@ -331,7 +331,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.87", + "syn 2.0.85", ] [[package]] @@ -434,7 +434,7 @@ dependencies = [ "cairo-lang-utils", "indoc", "num-bigint", - "num-traits", + "num-traits 0.2.19", "parity-scale-codec", "serde", ] @@ -568,7 +568,7 @@ dependencies = [ "itertools 0.12.1", "log", "num-bigint", - "num-traits", + "num-traits 0.2.19", "rust-analyzer-salsa", "smol_str", ] @@ -587,7 +587,7 @@ dependencies = [ "colored", "itertools 0.12.1", "num-bigint", - "num-traits", + "num-traits 0.2.19", "rust-analyzer-salsa", "smol_str", "unescaper", @@ -620,7 +620,7 @@ checksum = "d72f17373740f242d6995e896b9195c2cedff7e8b14e496afdd16b405039d1fb" dependencies = [ "cairo-lang-debug", "quote", - "syn 2.0.87", + "syn 2.0.85", ] [[package]] @@ -660,7 +660,7 @@ dependencies = [ "keccak", "num-bigint", "num-integer", - "num-traits", + "num-traits 0.2.19", "rand", "sha2", "smol_str", @@ -688,7 +688,7 @@ dependencies = [ "indoc", "itertools 0.12.1", "num-bigint", - "num-traits", + "num-traits 0.2.19", "rust-analyzer-salsa", "smol_str", "toml", @@ -710,7 +710,7 @@ dependencies = [ "lalrpop-util", "num-bigint", "num-integer", - "num-traits", + "num-traits 0.2.19", "regex", "rust-analyzer-salsa", "serde", @@ -733,7 +733,7 @@ dependencies = [ "cairo-lang-utils", "itertools 0.12.1", "num-bigint", - "num-traits", + "num-traits 0.2.19", "thiserror", ] @@ -749,7 +749,7 @@ dependencies = [ "cairo-lang-utils", "itertools 0.12.1", "num-bigint", - "num-traits", + "num-traits 0.2.19", "thiserror", ] @@ -770,7 +770,7 @@ dependencies = [ "cairo-lang-syntax", "cairo-lang-utils", "itertools 0.12.1", - "num-traits", + "num-traits 0.2.19", "rust-analyzer-salsa", "serde", "serde_json", @@ -793,7 +793,7 @@ dependencies = [ "indoc", "itertools 0.12.1", "num-bigint", - "num-traits", + "num-traits 0.2.19", "starknet-types-core", "thiserror", ] @@ -852,7 +852,7 @@ dependencies = [ "itertools 0.12.1", "num-bigint", "num-integer", - "num-traits", + "num-traits 0.2.19", "serde", "serde_json", "sha3", @@ -871,7 +871,7 @@ dependencies = [ "cairo-lang-filesystem", "cairo-lang-utils", "num-bigint", - "num-traits", + "num-traits 0.2.19", "rust-analyzer-salsa", "smol_str", "unescaper", @@ -909,7 +909,7 @@ dependencies = [ "indoc", "itertools 0.12.1", "num-bigint", - "num-traits", + "num-traits 0.2.19", "serde", "starknet-types-core", ] @@ -937,7 +937,7 @@ dependencies = [ "indexmap 2.6.0", "itertools 0.12.1", "num-bigint", - "num-traits", + "num-traits 0.2.19", "schemars", "serde", ] @@ -984,7 +984,7 @@ dependencies = [ "mlir-sys", "num-bigint", "num-integer", - "num-traits", + "num-traits 0.2.19", "pretty_assertions_sorted", "proptest", "rayon", @@ -1012,7 +1012,7 @@ dependencies = [ "cairo-lang-sierra-gas", "itertools 0.13.0", "lazy_static", - "num-traits", + "num-traits 0.2.19", "rand", "starknet-curve 0.5.1", "starknet-types-core", @@ -1041,7 +1041,7 @@ dependencies = [ "num-bigint", "num-integer", "num-prime", - "num-traits", + "num-traits 0.2.19", "rand", "rust_decimal", "serde", @@ -1081,9 +1081,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.1.35" +version = "1.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f57c4b4da2a9d619dd035f27316d7a426305b75be93d09e92f2b9229c34feaf" +checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" dependencies = [ "jobserver", "libc", @@ -1184,7 +1184,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.85", ] [[package]] @@ -1311,7 +1311,7 @@ dependencies = [ "criterion-plot", "is-terminal", "itertools 0.10.5", - "num-traits", + "num-traits 0.2.19", "once_cell", "oorandom", "plotters", @@ -1407,7 +1407,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.87", + "syn 2.0.85", ] [[package]] @@ -1418,7 +1418,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.87", + "syn 2.0.85", ] [[package]] @@ -1485,7 +1485,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.85", ] [[package]] @@ -1495,7 +1495,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.87", + "syn 2.0.85", ] [[package]] @@ -1566,7 +1566,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.85", ] [[package]] @@ -1613,7 +1613,7 @@ checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.85", ] [[package]] @@ -1728,7 +1728,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.85", ] [[package]] @@ -1786,7 +1786,7 @@ checksum = "553630feadf7b76442b0849fd25fdf89b860d933623aec9693fed19af0400c78" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.85", ] [[package]] @@ -1833,12 +1833,12 @@ dependencies = [ [[package]] name = "good_lp" -version = "1.9.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b1668836f82863fed48defee60296cde17ee0beffa7b9be29dc2496747bafb4" +checksum = "3198bd13dea84c76a64621d6ee8ee26a4960a9a0d538eca95ca8f1320a469ac9" dependencies = [ "fnv", - "microlp", + "minilp", ] [[package]] @@ -1879,9 +1879,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.1" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" dependencies = [ "allocator-api2", "equivalent", @@ -2021,7 +2021,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.15.1", + "hashbrown 0.15.0", "serde", ] @@ -2291,7 +2291,7 @@ version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown 0.15.1", + "hashbrown 0.15.0", ] [[package]] @@ -2305,11 +2305,10 @@ dependencies = [ [[package]] name = "matrixmultiply" -version = "0.3.9" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9380b911e3e96d10c1f415da0876389aaf1b56759054eeb0de7df940c456ba1a" +checksum = "916806ba0031cd542105d916a97c8572e1fa6dd79c9c51e7eb43a09ec2dd84c1" dependencies = [ - "autocfg", "rawpointer", ] @@ -2337,7 +2336,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.87", + "syn 2.0.85", "tblgen-alt", "unindent", ] @@ -2349,10 +2348,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] -name = "microlp" -version = "0.2.4" +name = "minilp" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be6fbd22ab75d94d6e4419c2225a62ae22410c9ae1ecb4d743a1df906a55ca4" +checksum = "82a7750a9e5076c660b7bec5e6457b4dbff402b9863c8d112891434e18fd5385" dependencies = [ "log", "sprs", @@ -2384,16 +2383,14 @@ dependencies = [ [[package]] name = "ndarray" -version = "0.16.1" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "882ed72dce9365842bf196bdeedf5055305f11fc8c03dee7bb0194a6cad34841" +checksum = "ac06db03ec2f46ee0ecdca1a1c34a99c0d188a0d83439b84bf0cb4b386e4ab09" dependencies = [ "matrixmultiply", "num-complex", "num-integer", - "num-traits", - "portable-atomic", - "portable-atomic-util", + "num-traits 0.2.19", "rawpointer", ] @@ -2430,18 +2427,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ "num-integer", - "num-traits", + "num-traits 0.2.19", "rand", "serde", ] [[package]] name = "num-complex" -version = "0.4.6" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95" dependencies = [ - "num-traits", + "autocfg", + "num-traits 0.2.19", ] [[package]] @@ -2456,7 +2454,7 @@ version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "num-traits", + "num-traits 0.2.19", ] [[package]] @@ -2467,7 +2465,7 @@ checksum = "64a5fe11d4135c3bcdf3a95b18b194afa9608a5f6ff034f5d857bc9a27fb0119" dependencies = [ "num-bigint", "num-integer", - "num-traits", + "num-traits 0.2.19", ] [[package]] @@ -2482,10 +2480,19 @@ dependencies = [ "num-bigint", "num-integer", "num-modular", - "num-traits", + "num-traits 0.2.19", "rand", ] +[[package]] +name = "num-traits" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" +dependencies = [ + "num-traits 0.2.19", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -2520,7 +2527,7 @@ version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c" dependencies = [ - "num-traits", + "num-traits 0.2.19", ] [[package]] @@ -2662,7 +2669,7 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" dependencies = [ - "num-traits", + "num-traits 0.2.19", "plotters-backend", "plotters-svg", "wasm-bindgen", @@ -2690,15 +2697,6 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" -[[package]] -name = "portable-atomic-util" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90a7d5beecc52a491b54d6dd05c7a45ba1801666a5baad9fdbfc6fef8d2d206c" -dependencies = [ - "portable-atomic", -] - [[package]] name = "powerfmt" version = "0.2.0" @@ -2747,7 +2745,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" dependencies = [ "proc-macro2", - "syn 2.0.87", + "syn 2.0.85", ] [[package]] @@ -2802,7 +2800,7 @@ dependencies = [ "bit-vec", "bitflags", "lazy_static", - "num-traits", + "num-traits 0.2.19", "rand", "rand_chacha", "rand_xorshift", @@ -3010,7 +3008,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn 2.0.87", + "syn 2.0.85", "unicode-ident", ] @@ -3040,7 +3038,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.85", ] [[package]] @@ -3050,7 +3048,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b082d80e3e3cc52b2ed634388d436fe1f4de6af5786cc2de9ba9737527bdf555" dependencies = [ "arrayvec", - "num-traits", + "num-traits 0.2.19", ] [[package]] @@ -3070,9 +3068,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.39" +version = "0.38.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "375116bee2be9ed569afe2154ea6a99dfdffd257f533f187498c2a8f5feaf4ee" +checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a" dependencies = [ "bitflags", "errno", @@ -3166,7 +3164,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.87", + "syn 2.0.85", ] [[package]] @@ -3201,7 +3199,7 @@ checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.85", ] [[package]] @@ -3212,7 +3210,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.85", ] [[package]] @@ -3331,14 +3329,13 @@ checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "sprs" -version = "0.11.2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "704ef26d974e8a452313ed629828cd9d4e4fa34667ca1ad9d6b1fffa43c6e166" +checksum = "ec63571489873d4506683915840eeb1bb16b3198ee4894cc6f2fe3013d505e56" dependencies = [ "ndarray", "num-complex", - "num-traits", - "smallvec", + "num-traits 0.1.43", ] [[package]] @@ -3358,7 +3355,7 @@ dependencies = [ "hmac", "num-bigint", "num-integer", - "num-traits", + "num-traits 0.2.19", "rfc6979", "sha2", "starknet-crypto-codegen", @@ -3375,7 +3372,7 @@ checksum = "bbc159a1934c7be9761c237333a57febe060ace2bc9e3b337a59a37af206d19f" dependencies = [ "starknet-curve 0.4.2", "starknet-ff", - "syn 2.0.87", + "syn 2.0.85", ] [[package]] @@ -3419,7 +3416,7 @@ dependencies = [ "lazy_static", "num-bigint", "num-integer", - "num-traits", + "num-traits 0.2.19", "serde", ] @@ -3467,9 +3464,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.87" +version = "2.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56" dependencies = [ "proc-macro2", "quote", @@ -3536,7 +3533,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.85", ] [[package]] @@ -3547,28 +3544,28 @@ checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.85", "test-case-core", ] [[package]] name = "thiserror" -version = "1.0.68" +version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02dd99dc800bbb97186339685293e1cc5d9df1f8fae2d0aecd9ff1c77efea892" +checksum = "5d11abd9594d9b38965ef50805c5e469ca9cc6f197f883f717e0269a3057b3d5" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.68" +version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7c61ec9a6f64d2793d8a45faba21efbe3ced62a886d44c36a009b2b519b4c7e" +checksum = "ae71770322cbd277e69d762a16c444af02aa0575ac0d174f0b9562d3b37f8602" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.85", ] [[package]] @@ -3707,7 +3704,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.85", ] [[package]] @@ -3921,7 +3918,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.85", "wasm-bindgen-shared", ] @@ -3943,7 +3940,7 @@ checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.85", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4212,7 +4209,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.85", ] [[package]] @@ -4232,7 +4229,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.85", ] [[package]] From e188415796a2644472ab6174a47dd4b6edbfd4a9 Mon Sep 17 00:00:00 2001 From: FrancoGiachetta Date: Tue, 5 Nov 2024 17:03:57 -0300 Subject: [PATCH 26/31] fix cargo.lock --- .github/workflows/starknet-blocks.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/starknet-blocks.yml b/.github/workflows/starknet-blocks.yml index 13930362e..441d87ea3 100644 --- a/.github/workflows/starknet-blocks.yml +++ b/.github/workflows/starknet-blocks.yml @@ -27,7 +27,7 @@ jobs: components: clippy - uses: Swatinem/rust-cache@v2 with: - key: "ref-ae8b771795f3504101574ae8876fa80e3eb285d8" + key: "ref-0dfc3d9a8c85a2d6ee53e431bd8a21e2d6839a32" - name: Check and free hdd space left if: ${{ matrix.runner == 'native' }} @@ -76,7 +76,7 @@ jobs: uses: actions/checkout@v4 with: repository: lambdaclass/starknet-replay - ref: ae8b771795f3504101574ae8876fa80e3eb285d8 + ref: 0dfc3d9a8c85a2d6ee53e431bd8a21e2d6839a32 path: replay - name: Install Starknet Replay deps From 44f85af21f0ab0dd8614a7ae550f6b6b8582b873 Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Wed, 6 Nov 2024 15:18:01 +0100 Subject: [PATCH 27/31] works with leaks --- runtime/src/lib.rs | 4 ++ src/executor/contract.rs | 79 +++++++++++++++++++++++++++++++--- src/libfuncs/gas.rs | 93 +++++++++++++++++++--------------------- src/metadata/gas.rs | 6 +-- 4 files changed, 124 insertions(+), 58 deletions(-) diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 49130afe3..fc8217d98 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -493,10 +493,14 @@ pub extern "C" fn cairo_native__set_costs_builtin(ptr: *const u64) { /// Get the gas builtin from the internal thread local. #[no_mangle] pub extern "C" fn cairo_native__get_costs_builtin() -> *const u64 { + //dbg!(BUILTIN_COSTS.get()); if BUILTIN_COSTS.get().is_null() { // We shouldn't panic here, but we can print a big message. eprintln!("BUILTIN_COSTS POINTER IS NULL!"); } + //let ptr = BUILTIN_COSTS.get(); + //let x = unsafe { std::slice::from_raw_parts(ptr, 7) }; + //dbg!(x); BUILTIN_COSTS.get() } diff --git a/src/executor/contract.rs b/src/executor/contract.rs index c4495ad30..a4baf32ec 100644 --- a/src/executor/contract.rs +++ b/src/executor/contract.rs @@ -303,13 +303,14 @@ impl AotContractExecutor { let function_ptr = self.find_function_ptr(&function_id, true)?; let builtin_costs = builtin_costs.unwrap_or_default(); - let builtin_costs: [u64; 7] = builtin_costs.into(); + let builtin_costs_stack: [u64; 7] = builtin_costs.into(); + let builtin_costs = Box::into_raw(Box::new(builtin_costs_stack)); // set the builtin costs using the utility method to set the thread local let set_costs_builtin = unsafe { self.library .get::(b"cairo_native__set_costs_builtin")? }; - set_costs_builtin(builtin_costs.as_ptr()); + set_costs_builtin(builtin_costs.cast()); let initial_gas_cost = { let mut cost = 0; @@ -322,7 +323,7 @@ impl AotContractExecutor { .initial_cost .iter() { - let token_cost = builtin_costs[*offset as usize] * val; + let token_cost = builtin_costs_stack[*offset as usize] * val; cost += token_cost; } cost as u128 @@ -342,7 +343,7 @@ impl AotContractExecutor { let return_ptr = arena.alloc_layout(unsafe { // 64 = size of enum + builtin sizes // align is 16 because of the u128 from gas - Layout::from_size_align_unchecked(64 + builtins_size, 16) + Layout::from_size_align_unchecked(128 + builtins_size, 16) }); return_ptr.as_ptr().to_bytes(&mut invoke_data)?; @@ -356,7 +357,7 @@ impl AotContractExecutor { } BuiltinType::BuiltinCosts => { // todo: check if valid - builtin_costs.as_ptr().to_bytes(&mut invoke_data)?; + builtin_costs_stack.as_ptr().to_bytes(&mut invoke_data)?; } BuiltinType::System => { (&mut syscall_handler as *mut StarknetSyscallHandlerCallbacks<_>) @@ -613,6 +614,38 @@ mod tests { program } + #[fixture] + fn starknet_program_factorial() -> ContractClass { + let (_, program) = load_starknet_contract! { + #[starknet::interface] + trait ISimpleStorage { + fn get(self: @TContractState, x: felt252) -> felt252; + } + + #[starknet::contract] + mod contract { + #[storage] + struct Storage {} + + #[abi(embed_v0)] + impl ISimpleStorageImpl of super::ISimpleStorage { + fn get(self: @ContractState, x: felt252) -> felt252 { + factorial(1, x) + } + } + + fn factorial(value: felt252, n: felt252) -> felt252 { + if (n == 1) { + value + } else { + factorial(value * n, n - 1) + } + } + } + }; + program + } + #[fixture] fn starknet_program_empty() -> ContractClass { let (_, program) = load_starknet_contract! { @@ -711,6 +744,42 @@ mod tests { assert_eq!(result.return_values, vec![Felt::from(2), Felt::from(4)]); } + #[rstest] + #[case(OptLevel::Aggressive)] + fn test_contract_executor_factorial( + starknet_program_factorial: ContractClass, + #[case] optlevel: OptLevel, + ) { + let executor = AotContractExecutor::new( + &starknet_program_factorial.extract_sierra_program().unwrap(), + &starknet_program_factorial.entry_points_by_type, + optlevel, + ) + .unwrap(); + + // The last function in the program is the `get` wrapper function. + let selector = starknet_program_factorial + .entry_points_by_type + .external + .last() + .unwrap() + .selector + .clone(); + + let result = executor + .run( + Felt::from(&selector), + &[10.into()], + Some(u64::MAX as u128), + None, + &mut StubSyscallHandler::default(), + ) + .unwrap(); + + assert_eq!(result.return_values, vec![Felt::from(3628800)]); + assert_eq!(result.remaining_gas, 18446744073709533805); + } + #[rstest] #[case(OptLevel::None)] #[case(OptLevel::Default)] diff --git a/src/libfuncs/gas.rs b/src/libfuncs/gas.rs index b5ff098e8..ce50f673c 100644 --- a/src/libfuncs/gas.rs +++ b/src/libfuncs/gas.rs @@ -4,7 +4,7 @@ use super::LibfuncHelper; use crate::{ error::{Error, Result}, metadata::{gas::GasCost, runtime_bindings::RuntimeBindingsMeta, MetadataStorage}, - utils::BlockExt, + utils::{BlockExt, GepIndex}, }; use cairo_lang_sierra::{ extensions::{ @@ -17,7 +17,6 @@ use cairo_lang_sierra::{ use melior::{ dialect::{ arith::{self, CmpiPredicate}, - llvm::{self, r#type::pointer}, ods, }, ir::{r#type::IntegerType, Block, Location}, @@ -101,14 +100,14 @@ pub fn build_withdraw_gas<'ctx, 'this>( .into() }; - let mut final_gas_cost = entry.const_int_from_type(context, location, 0, u128_type)?; + let mut total_gas_cost_value = entry.const_int_from_type(context, location, 0, u128_type)?; - for (cost, token_type) in &gas_cost.0 { - if *cost == 0 { + for (cost_count, token_type) in &gas_cost.0 { + if *cost_count == 0 { continue; } - let token_type_index = match token_type { + let builtin_costs_index = match token_type { CostTokenType::Const => 0, CostTokenType::Pedersen => 1, CostTokenType::Bitwise => 2, @@ -119,44 +118,37 @@ pub fn build_withdraw_gas<'ctx, 'this>( _ => unreachable!(), }; - let gas_cost_val = entry.const_int_from_type(context, location, *cost, u128_type)?; - let token_type_index_val = - entry.const_int_from_type(context, location, token_type_index, u64_type)?; + let cost_count_value = + entry.const_int_from_type(context, location, *cost_count, u128_type)?; + let builtin_costs_index_value = + entry.const_int_from_type(context, location, builtin_costs_index, u64_type)?; - let token_cost_value_ptr = entry.append_op_result(llvm::get_element_ptr_dynamic( + let builtin_cost_value_ptr = entry.gep( context, + location, builtin_ptr, - &[token_type_index_val], + &[GepIndex::Value(builtin_costs_index_value)], u64_type, - pointer(context, 0), - location, - ))?; - let token_cost_multiplier_value = - entry.load(context, location, token_cost_value_ptr, u64_type)?; - let token_cost_multiplier_value = entry.append_op_result(arith::extui( - token_cost_multiplier_value, - u128_type, - location, - ))?; - let total_gas_cost_val = entry.append_op_result(arith::muli( - gas_cost_val, - token_cost_multiplier_value, - location, - ))?; - final_gas_cost = - entry.append_op_result(arith::addi(final_gas_cost, total_gas_cost_val, location))?; + )?; + let cost_value = entry.load(context, location, builtin_cost_value_ptr, u64_type)?; + let cost_value_ext = + entry.append_op_result(arith::extui(cost_value, u128_type, location))?; + let gas_cost_value = + entry.append_op_result(arith::muli(cost_count_value, cost_value_ext, location))?; + total_gas_cost_value = + entry.append_op_result(arith::addi(total_gas_cost_value, gas_cost_value, location))?; } let is_enough = entry.append_op_result(arith::cmpi( context, CmpiPredicate::Uge, current_gas, - final_gas_cost, + total_gas_cost_value, location, ))?; let resulting_gas = entry.append_op_result( - ods::llvm::intr_usub_sat(context, current_gas, final_gas_cost, location).into(), + ods::llvm::intr_usub_sat(context, current_gas, total_gas_cost_value, location).into(), )?; entry.append_operation(helper.cond_br( @@ -192,14 +184,14 @@ pub fn build_builtin_withdraw_gas<'ctx, 'this>( let u128_type: melior::ir::Type = IntegerType::new(context, 128).into(); let u64_type: melior::ir::Type = IntegerType::new(context, 64).into(); - let mut final_gas_cost = entry.const_int_from_type(context, location, 0, u128_type)?; + let mut total_gas_cost_value = entry.const_int_from_type(context, location, 0, u128_type)?; - for (cost, token_type) in &gas_cost.0 { - if *cost == 0 { + for (cost_count, token_type) in &gas_cost.0 { + if *cost_count == 0 { continue; } - let token_type_index = match token_type { + let builtin_costs_index = match token_type { CostTokenType::Const => 0, CostTokenType::Pedersen => 1, CostTokenType::Bitwise => 2, @@ -210,36 +202,37 @@ pub fn build_builtin_withdraw_gas<'ctx, 'this>( _ => unreachable!(), }; - let gas_cost_val = entry.const_int_from_type(context, location, *cost, u128_type)?; - let token_type_index_val = - entry.const_int_from_type(context, location, token_type_index, u64_type)?; + let cost_count_value = + entry.const_int_from_type(context, location, *cost_count, u128_type)?; + let builtin_costs_index_value = + entry.const_int_from_type(context, location, builtin_costs_index, u64_type)?; - let cost_value_ptr = entry.append_op_result(llvm::get_element_ptr_dynamic( + let builtin_cost_value_ptr = entry.gep( context, + location, builtin_ptr, - &[token_type_index_val], + &[GepIndex::Value(builtin_costs_index_value)], u64_type, - pointer(context, 0), - location, - ))?; - let cost_value = entry.load(context, location, cost_value_ptr, u64_type)?; - let cost_value = entry.append_op_result(arith::extui(cost_value, u128_type, location))?; - let total_gas_cost_val = - entry.append_op_result(arith::muli(gas_cost_val, cost_value, location))?; - final_gas_cost = - entry.append_op_result(arith::addi(final_gas_cost, total_gas_cost_val, location))?; + )?; + let cost_value = entry.load(context, location, builtin_cost_value_ptr, u64_type)?; + let cost_value_ext = + entry.append_op_result(arith::extui(cost_value, u128_type, location))?; + let gas_cost_value = + entry.append_op_result(arith::muli(cost_count_value, cost_value_ext, location))?; + total_gas_cost_value = + entry.append_op_result(arith::addi(total_gas_cost_value, gas_cost_value, location))?; } let is_enough = entry.append_op_result(arith::cmpi( context, CmpiPredicate::Uge, current_gas, - final_gas_cost, + total_gas_cost_value, location, ))?; let resulting_gas = entry.append_op_result( - ods::llvm::intr_usub_sat(context, current_gas, final_gas_cost, location).into(), + ods::llvm::intr_usub_sat(context, current_gas, total_gas_cost_value, location).into(), )?; entry.append_operation(helper.cond_br( diff --git a/src/metadata/gas.rs b/src/metadata/gas.rs index 6dd1dff98..d368c0c1c 100644 --- a/src/metadata/gas.rs +++ b/src/metadata/gas.rs @@ -136,11 +136,11 @@ impl GasMetadata { pub fn get_gas_costs_for_statement(&self, idx: StatementIdx) -> Vec<(u128, CostTokenType)> { let mut costs = Vec::new(); for cost_type in CostTokenType::iter_casm_tokens() { - if let Some(amount) = + if let Some(cost_count) = self.get_gas_cost_for_statement_and_cost_token_type(idx, *cost_type) { - if amount > 0 { - costs.push((amount, *cost_type)); + if cost_count > 0 { + costs.push((cost_count, *cost_type)); } } } From acc3a3b8c38c5ae52bad56c3388bad660bfadca6 Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Wed, 6 Nov 2024 15:34:54 +0100 Subject: [PATCH 28/31] fix --- runtime/src/lib.rs | 10 ++++------ src/executor.rs | 23 ++++++++++++++++++----- src/executor/aot.rs | 19 ++++++++++++------- src/executor/contract.rs | 24 ++++++++++++++++++++---- src/executor/jit.rs | 6 +++--- 5 files changed, 57 insertions(+), 25 deletions(-) diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index fc8217d98..4ab674b7b 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -483,24 +483,22 @@ thread_local! { }; } -/// Store the gas builtin in the internal thread local. +/// Store the gas builtin in the internal thread local. Returns the old pointer, to restore it after execution. /// Not a runtime metadata method, it should be called before the program is executed. #[no_mangle] -pub extern "C" fn cairo_native__set_costs_builtin(ptr: *const u64) { +pub extern "C" fn cairo_native__set_costs_builtin(ptr: *const u64) -> *const u64 { + let old = BUILTIN_COSTS.get(); BUILTIN_COSTS.set(ptr); + old } /// Get the gas builtin from the internal thread local. #[no_mangle] pub extern "C" fn cairo_native__get_costs_builtin() -> *const u64 { - //dbg!(BUILTIN_COSTS.get()); if BUILTIN_COSTS.get().is_null() { // We shouldn't panic here, but we can print a big message. eprintln!("BUILTIN_COSTS POINTER IS NULL!"); } - //let ptr = BUILTIN_COSTS.get(); - //let x = unsafe { std::slice::from_raw_parts(ptr, 7) }; - //dbg!(x); BUILTIN_COSTS.get() } diff --git a/src/executor.rs b/src/executor.rs index b6d70cd56..0553f620f 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -69,7 +69,7 @@ extern "C" { fn invoke_dynamic( registry: &ProgramRegistry, function_ptr: *const c_void, - set_builtin_costs_fnptr: extern "C" fn(*const u64), + set_builtin_costs_fnptr: extern "C" fn(*const u64) -> *const u64, function_signature: &FunctionSignature, args: &[Value], gas: u128, @@ -143,8 +143,13 @@ fn invoke_dynamic( }); // Order matters, for the libfunc impl - let builtin_costs: [u64; 7] = BuiltinCosts::default().into(); - set_builtin_costs_fnptr(builtin_costs.as_ptr()); + let builtin_costs_stack: [u64; 7] = BuiltinCosts::default().into(); + // Note: the ptr into a slice is valid, it can be used with cast() + // Care should be taken if you dereference it and take the .as_ptr() of the slice, since when you + // deref it, it will be a copy on the stack, so you will get the ptr of the value in the stack. + let builtin_costs: *mut [u64; 7] = Box::into_raw(Box::new(builtin_costs_stack)); + // We may be inside a recursive contract, save the possible saved builtin costs to restore it after our call. + let old_builtincosts_ptr = set_builtin_costs_fnptr(builtin_costs.cast()); // Generate argument list. let mut iter = args.iter(); @@ -172,8 +177,7 @@ fn invoke_dynamic( .to_bytes(&mut invoke_data)?; } CoreTypeConcrete::BuiltinCosts(_) => { - // todo: check if valid - (builtin_costs.as_ptr()).to_bytes(&mut invoke_data)?; + builtin_costs.to_bytes(&mut invoke_data)?; } type_info if type_info.is_builtin() => 0u64.to_bytes(&mut invoke_data)?, type_info => ValueWithInfoWrapper { @@ -320,6 +324,15 @@ fn invoke_dynamic( debug_name: None, }); + // Restore the old ptr and get back our builtincost box and free it. + let our_builtincosts_ptr = set_builtin_costs_fnptr(old_builtincosts_ptr); + + if !our_builtincosts_ptr.is_null() && old_builtincosts_ptr.is_aligned() { + unsafe { + let _ = Box::<[u64; 7]>::from_raw(our_builtincosts_ptr.cast_mut().cast()); + }; + } + #[cfg(feature = "with-mem-tracing")] crate::utils::mem_tracing::report_stats(); diff --git a/src/executor/aot.rs b/src/executor/aot.rs index e25cf504a..41b1565e2 100644 --- a/src/executor/aot.rs +++ b/src/executor/aot.rs @@ -82,10 +82,12 @@ impl AotNativeExecutor { .get_initial_available_gas(function_id, gas) .map_err(crate::error::Error::GasMetadataError)?; - let set_costs_builtin: extern "C" fn(*const u64) = unsafe { + let set_costs_builtin: extern "C" fn(*const u64) -> *const u64 = unsafe { std::mem::transmute( self.library - .get::(b"cairo_native__set_costs_builtin")? + .get:: *const u64>( + b"cairo_native__set_costs_builtin", + )? .into_raw() .into_raw(), ) @@ -114,10 +116,12 @@ impl AotNativeExecutor { .get_initial_available_gas(function_id, gas) .map_err(crate::error::Error::GasMetadataError)?; - let set_costs_builtin: extern "C" fn(*const u64) = unsafe { + let set_costs_builtin: extern "C" fn(*const u64) -> *const u64 = unsafe { std::mem::transmute( self.library - .get::(b"cairo_native__set_costs_builtin")? + .get:: *const u64>( + b"cairo_native__set_costs_builtin", + )? .into_raw() .into_raw(), ) @@ -146,10 +150,12 @@ impl AotNativeExecutor { .get_initial_available_gas(function_id, gas) .map_err(crate::error::Error::GasMetadataError)?; - let set_costs_builtin: extern "C" fn(*const u64) = unsafe { + let set_costs_builtin: extern "C" fn(*const u64) -> *const u64 = unsafe { std::mem::transmute( self.library - .get::(b"cairo_native__set_costs_builtin")? + .get:: *const u64>( + b"cairo_native__set_costs_builtin", + )? .into_raw() .into_raw(), ) @@ -164,7 +170,6 @@ impl AotNativeExecutor { fields: vec![Value::Array( args.iter().cloned().map(Value::Felt252).collect(), )], - // TODO: Populate `debug_name`. debug_name: None, }], available_gas, diff --git a/src/executor/contract.rs b/src/executor/contract.rs index a4baf32ec..a7a09ddbf 100644 --- a/src/executor/contract.rs +++ b/src/executor/contract.rs @@ -304,13 +304,18 @@ impl AotContractExecutor { let builtin_costs = builtin_costs.unwrap_or_default(); let builtin_costs_stack: [u64; 7] = builtin_costs.into(); - let builtin_costs = Box::into_raw(Box::new(builtin_costs_stack)); - // set the builtin costs using the utility method to set the thread local + // Note: the ptr into a slice is valid, it can be used with cast() + // Care should be taken if you dereference it and take the .as_ptr() of the slice, since when you + // deref it, it will be a copy on the stack, so you will get the ptr of the value in the stack. + let builtin_costs: *mut [u64; 7] = Box::into_raw(Box::new(builtin_costs_stack)); let set_costs_builtin = unsafe { self.library - .get::(b"cairo_native__set_costs_builtin")? + .get:: *const u64>( + b"cairo_native__set_costs_builtin", + )? }; - set_costs_builtin(builtin_costs.cast()); + // We may be inside a recursive contract, save the possible saved builtin costs to restore it after our call. + let old_builtincosts_ptr = set_costs_builtin(builtin_costs.cast()); let initial_gas_cost = { let mut cost = 0; @@ -535,6 +540,15 @@ impl AotContractExecutor { error_msg = Some(str_error); } + // Restore the old ptr and get back our builtincost box and free it. + let our_builtincosts_ptr = set_costs_builtin(old_builtincosts_ptr); + + if !our_builtincosts_ptr.is_null() && old_builtincosts_ptr.is_aligned() { + unsafe { + let _ = Box::<[u64; 7]>::from_raw(our_builtincosts_ptr.cast_mut().cast()); + }; + } + #[cfg(feature = "with-mem-tracing")] crate::utils::mem_tracing::report_stats(); @@ -590,6 +604,8 @@ mod tests { use rayon::iter::ParallelBridge; use rstest::*; + // todo add recursive contract test + #[fixture] fn starknet_program() -> ContractClass { let (_, program) = load_starknet_contract! { diff --git a/src/executor/jit.rs b/src/executor/jit.rs index a2c9dd9c2..440c95caf 100644 --- a/src/executor/jit.rs +++ b/src/executor/jit.rs @@ -76,7 +76,7 @@ impl<'m> JitNativeExecutor<'m> { .get_initial_available_gas(function_id, gas) .map_err(crate::error::Error::GasMetadataError)?; - let set_builtin_costs_fnptr: extern "C" fn(*const u64) = + let set_builtin_costs_fnptr: extern "C" fn(*const u64) -> *const u64 = unsafe { std::mem::transmute(self.engine.lookup("cairo_native__set_costs_builtin")) }; super::invoke_dynamic( @@ -103,7 +103,7 @@ impl<'m> JitNativeExecutor<'m> { .get_initial_available_gas(function_id, gas) .map_err(crate::error::Error::GasMetadataError)?; - let set_builtin_costs_fnptr: extern "C" fn(*const u64) = + let set_builtin_costs_fnptr: extern "C" fn(*const u64) -> *const u64 = unsafe { std::mem::transmute(self.engine.lookup("cairo_native__set_costs_builtin")) }; super::invoke_dynamic( @@ -129,7 +129,7 @@ impl<'m> JitNativeExecutor<'m> { .get_initial_available_gas(function_id, gas) .map_err(crate::error::Error::GasMetadataError)?; - let set_builtin_costs_fnptr: extern "C" fn(*const u64) = + let set_builtin_costs_fnptr: extern "C" fn(*const u64) -> *const u64 = unsafe { std::mem::transmute(self.engine.lookup("cairo_native__set_costs_builtin")) }; ContractExecutionResult::from_execution_result(super::invoke_dynamic( From 01994edd7bfb1943a8f47aa6eae3527b07230b83 Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Wed, 6 Nov 2024 15:43:29 +0100 Subject: [PATCH 29/31] upd replay --- .github/workflows/starknet-blocks.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/starknet-blocks.yml b/.github/workflows/starknet-blocks.yml index 441d87ea3..99665cace 100644 --- a/.github/workflows/starknet-blocks.yml +++ b/.github/workflows/starknet-blocks.yml @@ -27,7 +27,7 @@ jobs: components: clippy - uses: Swatinem/rust-cache@v2 with: - key: "ref-0dfc3d9a8c85a2d6ee53e431bd8a21e2d6839a32" + key: "ref-dc35685315f4df544d5d1cf006d3a2a25d8c2c9a" - name: Check and free hdd space left if: ${{ matrix.runner == 'native' }} @@ -76,7 +76,7 @@ jobs: uses: actions/checkout@v4 with: repository: lambdaclass/starknet-replay - ref: 0dfc3d9a8c85a2d6ee53e431bd8a21e2d6839a32 + ref: dc35685315f4df544d5d1cf006d3a2a25d8c2c9a path: replay - name: Install Starknet Replay deps From cdb84b2abf340951311ec06fb5bb9a6cfef42989 Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Thu, 7 Nov 2024 07:56:58 +0100 Subject: [PATCH 30/31] fix bench --- programs/benches/factorial_2M.c | 4 +--- programs/benches/fib_2M.c | 3 +-- programs/benches/logistic_map.c | 3 +-- scripts/bench-hyperfine.sh | 7 ++++--- 4 files changed, 7 insertions(+), 10 deletions(-) diff --git a/programs/benches/factorial_2M.c b/programs/benches/factorial_2M.c index f07ff4686..992f8648d 100644 --- a/programs/benches/factorial_2M.c +++ b/programs/benches/factorial_2M.c @@ -20,9 +20,7 @@ typedef struct factorial_return_values static void run_bench(factorial_return_values_t*, uint64_t) __attribute__((weakref("_mlir_ciface_factorial_2M::factorial_2M::main(f1)"))); -static void cairo_native__set_costs_builtin(uint64_t*) -__attribute__((weakref("cairo_native__set_costs_builtin"))); - +extern uint64_t* cairo_native__set_costs_builtin(uint64_t*); int main() { diff --git a/programs/benches/fib_2M.c b/programs/benches/fib_2M.c index 0fd4404ad..ffbec9785 100644 --- a/programs/benches/fib_2M.c +++ b/programs/benches/fib_2M.c @@ -20,8 +20,7 @@ typedef struct fib_return_values static void run_bench(fib_return_values_t *, uint64_t) __attribute__((weakref("_mlir_ciface_fib_2M::fib_2M::main(f1)"))); -static void cairo_native__set_costs_builtin(uint64_t*) -__attribute__((weakref("cairo_native__set_costs_builtin"))); +extern uint64_t* cairo_native__set_costs_builtin(uint64_t*); int main() { diff --git a/programs/benches/logistic_map.c b/programs/benches/logistic_map.c index 12493d39e..5d88dfb89 100644 --- a/programs/benches/logistic_map.c +++ b/programs/benches/logistic_map.c @@ -20,8 +20,7 @@ typedef struct map_return_values static void run_bench(map_return_values_t *, uint64_t) __attribute__((weakref("_mlir_ciface_logistic_map::logistic_map::main(f2)"))); -static void cairo_native__set_costs_builtin(uint64_t*) -__attribute__((weakref("cairo_native__set_costs_builtin"))); +extern uint64_t* cairo_native__set_costs_builtin(uint64_t*); int main() { diff --git a/scripts/bench-hyperfine.sh b/scripts/bench-hyperfine.sh index bad57a13a..cf2111c02 100755 --- a/scripts/bench-hyperfine.sh +++ b/scripts/bench-hyperfine.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # Configuration. -ROOT_DIR="$(dirname "$(dirname "${0%/*}")")" +ROOT_DIR="$(dirname "$(readlink -f "${0%/*}")")" MLIR_DIR="$MLIR_SYS_190_PREFIX" CAIRO_SRCS=$(find \ @@ -49,14 +49,15 @@ run_bench() { "$MLIR_DIR/bin/clang" \ -O3 \ - -g \ -march=native \ -mtune=native \ + -fPIC \ -Wno-override-module \ "$base_path.c" \ - -L "$OUTPUT_DIR/" \ + -L"$OUTPUT_DIR/" \ -Wl,-rpath "$MLIR_DIR/lib" \ -Wl,-rpath "$OUTPUT_DIR" \ + -Wl,--rpath-link "$OUTPUT_DIR" \ -lm \ -l"$base_name" \ -o "$OUTPUT_DIR/$base_name-march-native" \ From 5a5d1b3a29e46edeb77cb78c39f668f9eea73f82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juli=C3=A1n=20Gonz=C3=A1lez=20Calder=C3=B3n?= Date: Fri, 8 Nov 2024 17:18:33 -0300 Subject: [PATCH 31/31] Reorder deps --- scripts/bench-hyperfine.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/bench-hyperfine.sh b/scripts/bench-hyperfine.sh index cf2111c02..473c67265 100755 --- a/scripts/bench-hyperfine.sh +++ b/scripts/bench-hyperfine.sh @@ -58,8 +58,8 @@ run_bench() { -Wl,-rpath "$MLIR_DIR/lib" \ -Wl,-rpath "$OUTPUT_DIR" \ -Wl,--rpath-link "$OUTPUT_DIR" \ - -lm \ -l"$base_name" \ + -lm \ -o "$OUTPUT_DIR/$base_name-march-native" \ >> /dev/stderr