From 8e85c06f207da2a22282653a3d8c329ff2c536c6 Mon Sep 17 00:00:00 2001 From: Edgar Date: Tue, 20 Aug 2024 12:35:07 +0200 Subject: [PATCH] add failing test --- Cargo.toml | 10 ++-- programs/syscalls.cairo | 114 ++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 22 ++++++++ src/main.rs | 14 ++--- src/vm/starknet.rs | 6 ++- tests/syscalls.rs | 62 ++++++++++++++++++++++ 6 files changed, 211 insertions(+), 17 deletions(-) create mode 100644 programs/syscalls.cairo create mode 100644 tests/syscalls.rs diff --git a/Cargo.toml b/Cargo.toml index 38038ac..ee85895 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,16 +4,16 @@ version = "0.1.0" edition = "2021" [dependencies] -cairo-lang-sierra = "2.7.0" -cairo-lang-utils = "2.7.0" -clap = { version = "4.5.11", features = ["derive"] } +cairo-lang-sierra = "2.7.1" +cairo-lang-utils = "2.7.1" +clap = { version = "4.5.16", features = ["derive"] } k256 = "0.13.3" keccak = "0.1.5" num-bigint = "0.4.6" p256 = "0.13.2" sec1 = { version = "0.7.3", features = ["std"] } -serde = { version = "1.0.204", features = ["derive"] } -serde_json = "1.0.121" +serde = { version = "1.0.208", features = ["derive"] } +serde_json = "1.0.125" sha2 = { version = "0.10.8", features = ["compress"] } smallvec = "1.13.2" starknet-crypto = "0.7.1" diff --git a/programs/syscalls.cairo b/programs/syscalls.cairo new file mode 100644 index 0000000..3328400 --- /dev/null +++ b/programs/syscalls.cairo @@ -0,0 +1,114 @@ +use core::starknet::{ + call_contract_syscall, class_hash_const, contract_address_const, ContractAddress, + deploy_syscall, emit_event_syscall, ExecutionInfo, get_block_hash_syscall, + keccak_syscall, + library_call_syscall, replace_class_syscall, send_message_to_l1_syscall, + storage_address_try_from_felt252, storage_read_syscall, storage_write_syscall, SyscallResult, + testing::cheatcode, +}; +use core::starknet::syscalls::get_execution_info_syscall; +use core::starknet::syscalls::get_execution_info_v2_syscall; + +fn get_block_hash() -> SyscallResult { + get_block_hash_syscall(0) +} + +fn get_execution_info() -> SyscallResult> { + get_execution_info_syscall() +} + +fn get_execution_info_v2() -> SyscallResult> { + get_execution_info_v2_syscall() +} + +fn deploy() -> SyscallResult<(ContractAddress, Span)> { + deploy_syscall(class_hash_const::<0>(), 0, array![].span(), false) +} + +fn replace_class() -> SyscallResult<()> { + replace_class_syscall(class_hash_const::<0>()) +} + +fn library_call() -> SyscallResult> { + library_call_syscall(class_hash_const::<0>(), 0, array![].span()) +} + +fn call_contract() -> SyscallResult> { + call_contract_syscall(contract_address_const::<0>(), 0, array![].span()) +} + +fn storage_read() -> felt252 { + storage_read_syscall(0, storage_address_try_from_felt252(0).unwrap()).unwrap() +} + +fn storage_write() { + storage_write_syscall(0, storage_address_try_from_felt252(0).unwrap(), 0).unwrap() +} + +fn emit_event() -> SyscallResult<()> { + emit_event_syscall(array![].span(), array![].span()) +} + +fn send_message_to_l1() -> SyscallResult<()> { + send_message_to_l1_syscall(3, array![2].span()) +} + +fn keccak() -> SyscallResult { + keccak_syscall(array![].span()) +} + +fn set_sequencer_address(address: felt252) -> Span { + return cheatcode::<'set_sequencer_address'>(array![address].span()); +} + +fn set_account_contract_address(address: felt252) -> Span { + return cheatcode::<'set_account_contract_address'>(array![address].span()); +} + +fn set_block_number(number: felt252) -> Span { + return cheatcode::<'set_block_number'>(array![number].span()); +} + +fn set_block_timestamp(timestamp: felt252) -> Span { + return cheatcode::<'set_block_timestamp'>(array![timestamp].span()); +} + +fn set_caller_address(address: felt252) -> Span { + return cheatcode::<'set_caller_address'>(array![address].span()); +} + +fn set_chain_id(id: felt252) -> Span { + return cheatcode::<'set_chain_id'>(array![id].span()); +} + +fn set_contract_address(address: felt252) -> Span { + return cheatcode::<'set_contract_address'>(array![address].span()); +} + +fn set_max_fee(fee: felt252) -> Span { + return cheatcode::<'set_max_fee'>(array![fee].span()); +} + +fn set_nonce(nonce: felt252) -> Span { + return cheatcode::<'set_nonce'>(array![nonce].span()); +} + +fn set_signature(signature: Array) -> Span { + return cheatcode::<'set_signature'>(signature.span()); +} + +fn set_transaction_hash(hash: felt252) -> Span { + return cheatcode::<'set_transaction_hash'>(array![hash].span()); +} + +fn set_version(version: felt252) -> Span { + return cheatcode::<'set_version'>(array![version].span()); +} + +fn pop_log(log: felt252) -> Span { + return cheatcode::<'pop_log'>(array![log].span()); +} + +fn pop_l2_to_l1_message(message: felt252) -> Span { + return cheatcode::<'pop_l2_to_l1_message'>(array![message].span()); +} diff --git a/src/lib.rs b/src/lib.rs index 5004c05..fd94664 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,28 @@ +use cairo_lang_sierra::program::{GenFunction, Program, StatementIdx}; + pub use self::{dump::*, value::*, vm::VirtualMachine}; mod dump; pub mod starknet; mod value; mod vm; + +pub fn find_entry_point_by_idx( + program: &Program, + entry_point_idx: usize, +) -> Option<&GenFunction> { + program + .funcs + .iter() + .find(|x| x.id.id == entry_point_idx as u64) +} + +pub fn find_entry_point_by_name<'a>( + program: &'a Program, + name: &str, +) -> Option<&'a GenFunction> { + program + .funcs + .iter() + .find(|x| x.id.debug_name.as_ref().map(|x| x.as_str()) == Some(name)) +} diff --git a/src/main.rs b/src/main.rs index ab010b0..89d1cc2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -101,7 +101,9 @@ mod test { use cairo_lang_compiler::CompilerConfig; use cairo_lang_sierra::program::{GenFunction, Program, StatementIdx}; use cairo_lang_starknet::compile::compile_path; - use sierra_emu::{ContractExecutionResult, ProgramTrace, StateDump, VirtualMachine}; + use sierra_emu::{ + find_entry_point_by_idx, ContractExecutionResult, ProgramTrace, StateDump, VirtualMachine, + }; #[test] fn test_contract() { @@ -181,14 +183,4 @@ mod test { // let trace_str = serde_json::to_string_pretty(&trace).unwrap(); // std::fs::write("contract_trace.json", trace_str).unwrap(); } - - pub fn find_entry_point_by_idx( - program: &Program, - entry_point_idx: usize, - ) -> Option<&GenFunction> { - program - .funcs - .iter() - .find(|x| x.id.id == entry_point_idx as u64) - } } diff --git a/src/vm/starknet.rs b/src/vm/starknet.rs index 3770532..e27b659 100644 --- a/src/vm/starknet.rs +++ b/src/vm/starknet.rs @@ -538,7 +538,11 @@ fn eval_get_execution_info_v2( match result { Ok(res) => EvalAction::NormalBranch( 0, - smallvec![Value::U128(gas), system, res.into_value(felt_ty, out_ty_id.clone())], + smallvec![ + Value::U128(gas), + system, + res.into_value(felt_ty, out_ty_id.clone()) + ], ), Err(e) => EvalAction::NormalBranch( 1, diff --git a/tests/syscalls.rs b/tests/syscalls.rs new file mode 100644 index 0000000..12b0a1d --- /dev/null +++ b/tests/syscalls.rs @@ -0,0 +1,62 @@ +use std::{path::Path, sync::Arc}; + +use cairo_lang_compiler::{compile_cairo_project_at_path, CompilerConfig}; +use cairo_lang_sierra::program::{GenFunction, Program, StatementIdx}; +use sierra_emu::{ProgramTrace, StateDump, VirtualMachine}; + +fn run_syscall(func_name: &str) -> ProgramTrace { + let path = Path::new("programs/syscalls.cairo"); + + let sierra_program = Arc::new( + compile_cairo_project_at_path( + path, + CompilerConfig { + replace_ids: true, + ..Default::default() + }, + ) + .unwrap(), + ); + + let function = find_entry_point_by_name(&sierra_program, func_name).unwrap(); + + let mut vm = VirtualMachine::new(sierra_program.clone()); + + let calldata = []; + let initial_gas = 1000000; + + vm.call_contract(function, initial_gas, calldata); + + let mut trace = ProgramTrace::new(); + + while let Some((statement_idx, state)) = vm.step() { + trace.push(StateDump::new(statement_idx, state)); + } + + trace +} + +#[test] +fn test_contract_constructor() { + let mut trace = run_syscall("syscalls::syscalls::get_execution_info_v2"); +} + +pub fn find_entry_point_by_idx( + program: &Program, + entry_point_idx: usize, +) -> Option<&GenFunction> { + program + .funcs + .iter() + .find(|x| x.id.id == entry_point_idx as u64) +} + +pub fn find_entry_point_by_name<'a>( + program: &'a Program, + name: &str, +) -> Option<&'a GenFunction> { + program + .funcs + .iter() + .find(|x| x.id.debug_name.as_ref().map(|x| x.as_str()) == Some(name)) +}