diff --git a/cairo_vm_hints/src/hint_processor/mod.rs b/cairo_vm_hints/src/hint_processor/mod.rs index 79c42064..730c7873 100644 --- a/cairo_vm_hints/src/hint_processor/mod.rs +++ b/cairo_vm_hints/src/hint_processor/mod.rs @@ -2,8 +2,10 @@ pub mod input; pub mod models; pub mod output; -use crate::hints::{lib, vars}; -use crate::syscall_handler::SyscallHandlerWrapper; +use crate::{ + hints::{lib, vars}, + syscall_handler::evm::dryrun::SyscallHandlerWrapper, +}; use cairo_lang_casm::{ hints::{Hint, StarknetHint}, operand::{BinOpOperand, DerefOrImmediate, Operation, Register, ResOperand}, diff --git a/cairo_vm_hints/src/hints/lib/contract_bootloader/scopes.rs b/cairo_vm_hints/src/hints/lib/contract_bootloader/scopes.rs index 976883d4..c92c3d9d 100644 --- a/cairo_vm_hints/src/hints/lib/contract_bootloader/scopes.rs +++ b/cairo_vm_hints/src/hints/lib/contract_bootloader/scopes.rs @@ -1,4 +1,4 @@ -use crate::{hints::vars, syscall_handler::SyscallHandlerWrapper}; +use crate::{hints::vars, syscall_handler::evm::dryrun::SyscallHandlerWrapper}; use cairo_vm::{ hint_processor::builtin_hint_processor::builtin_hint_processor_definition::HintProcessorData, types::exec_scope::ExecutionScopes, diff --git a/cairo_vm_hints/src/hints/lib/contract_bootloader/syscall_handler.rs b/cairo_vm_hints/src/hints/lib/contract_bootloader/syscall_handler.rs index 161cfaa5..33278e20 100644 --- a/cairo_vm_hints/src/hints/lib/contract_bootloader/syscall_handler.rs +++ b/cairo_vm_hints/src/hints/lib/contract_bootloader/syscall_handler.rs @@ -1,4 +1,4 @@ -use crate::{hints::vars, syscall_handler::SyscallHandlerWrapper}; +use crate::{hints::vars, syscall_handler::evm::dryrun::SyscallHandlerWrapper}; use cairo_vm::{ hint_processor::builtin_hint_processor::{builtin_hint_processor_definition::HintProcessorData, hint_utils::get_ptr_from_var_name}, types::exec_scope::ExecutionScopes, diff --git a/cairo_vm_hints/src/main.rs b/cairo_vm_hints/src/main.rs index 6cf64017..bee1707d 100644 --- a/cairo_vm_hints/src/main.rs +++ b/cairo_vm_hints/src/main.rs @@ -14,7 +14,9 @@ use cairo_vm::vm::runners::cairo_runner::CairoRunner; use clap::{Parser, ValueHint}; use hdp_cairo_vm_hints::HdpOsError; use hint_processor::CustomHintProcessor; -use std::path::PathBuf; +use hints::vars; +use std::{fs, path::PathBuf}; +use syscall_handler::evm::dryrun::{SyscallHandler, SyscallHandlerWrapper}; #[derive(Parser, Debug)] #[clap(author, version, about, long_about = None)] @@ -28,6 +30,8 @@ struct Args { proof_mode: bool, #[structopt(long = "program_input")] program_input: PathBuf, + #[structopt(long = "program_output")] + program_output: PathBuf, } fn main() -> Result<(), HdpOsError> { @@ -69,5 +73,20 @@ fn main() -> Result<(), HdpOsError> { .map_err(|err| VmException::from_vm_error(&cairo_runner, err)) .map_err(|e| HdpOsError::Runner(e.into()))?; + fs::write( + args.program_output, + serde_json::to_vec::( + &cairo_runner + .exec_scopes + .get::(vars::scopes::SYSCALL_HANDLER) + .unwrap() + .syscall_handler + .try_read() + .unwrap(), + ) + .unwrap(), + ) + .unwrap(); + Ok(()) } diff --git a/cairo_vm_hints/src/syscall_handler/evm/dryrun/account.rs b/cairo_vm_hints/src/syscall_handler/evm/dryrun/account.rs index 70c731c1..8557db81 100644 --- a/cairo_vm_hints/src/syscall_handler/evm/dryrun/account.rs +++ b/cairo_vm_hints/src/syscall_handler/evm/dryrun/account.rs @@ -1,7 +1,6 @@ use crate::syscall_handler::{ traits::CallHandler, utils::{SyscallExecutionError, SyscallResult}, - Relocatable, VirtualMachine, }; use crate::{ cairo_types::{ @@ -18,7 +17,11 @@ use alloy::{ primitives::{Address, BlockNumber, ChainId}, transports::http::reqwest::Url, }; -use cairo_vm::{vm::errors::memory_errors::MemoryError, Felt252}; +use cairo_vm::{ + types::relocatable::Relocatable, + vm::{errors::memory_errors::MemoryError, vm_core::VirtualMachine}, + Felt252, +}; use serde::{Deserialize, Serialize}; use std::env; @@ -77,7 +80,7 @@ impl CairoType for CairoKey { } } -#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] pub struct Key { chain_id: ChainId, block_number: BlockNumber, diff --git a/cairo_vm_hints/src/syscall_handler/evm/dryrun/header.rs b/cairo_vm_hints/src/syscall_handler/evm/dryrun/header.rs index e9368c04..180cb1e5 100644 --- a/cairo_vm_hints/src/syscall_handler/evm/dryrun/header.rs +++ b/cairo_vm_hints/src/syscall_handler/evm/dryrun/header.rs @@ -1,7 +1,6 @@ use crate::syscall_handler::{ traits::CallHandler, utils::{SyscallExecutionError, SyscallResult}, - Relocatable, VirtualMachine, }; use crate::{ cairo_types::{ @@ -18,7 +17,11 @@ use alloy::{ primitives::{BlockNumber, ChainId}, transports::http::reqwest::Url, }; -use cairo_vm::{vm::errors::memory_errors::MemoryError, Felt252}; +use cairo_vm::{ + types::relocatable::Relocatable, + vm::{errors::memory_errors::MemoryError, vm_core::VirtualMachine}, + Felt252, +}; use serde::{Deserialize, Serialize}; use std::env; @@ -75,7 +78,7 @@ impl CairoType for CairoKey { } } -#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] pub struct Key { chain_id: ChainId, block_number: BlockNumber, diff --git a/cairo_vm_hints/src/syscall_handler/evm/dryrun/mod.rs b/cairo_vm_hints/src/syscall_handler/evm/dryrun/mod.rs index 9573322e..c64a9801 100644 --- a/cairo_vm_hints/src/syscall_handler/evm/dryrun/mod.rs +++ b/cairo_vm_hints/src/syscall_handler/evm/dryrun/mod.rs @@ -6,20 +6,35 @@ pub mod storage; pub mod transaction; use crate::cairo_types::traits::CairoType; -use crate::syscall_handler::traits::CallHandler; +use crate::syscall_handler::traits::{self, CallHandler}; +use crate::syscall_handler::utils::{run_handler, SyscallSelector}; use crate::{ cairo_types::new_syscalls::{CallContractRequest, CallContractResponse}, - syscall_handler::{ - traits::SyscallHandler, - utils::{felt_from_ptr, SyscallExecutionError, SyscallResult, WriteResponseResult}, - }, + syscall_handler::utils::{felt_from_ptr, SyscallExecutionError, SyscallResult, WriteResponseResult}, }; +use cairo_vm::vm::errors::hint_errors::HintError; use cairo_vm::{types::relocatable::Relocatable, vm::vm_core::VirtualMachine, Felt252}; use serde::{Deserialize, Serialize}; use serde_json::Value; +use std::rc::Rc; +use std::sync::RwLock; use std::{collections::HashSet, hash::Hash, marker::PhantomData}; use strum_macros::FromRepr; +#[derive(Debug, Default, Serialize, Deserialize)] +pub struct SyscallHandler { + #[serde(skip)] + syscall_ptr: Option, + call_contract_handler: CallContractHandler, +} + +/// SyscallHandler is wrapped in Rc> in order +/// to clone the reference when entering and exiting vm scopes +#[derive(Debug, Clone, Default)] +pub struct SyscallHandlerWrapper { + pub syscall_handler: Rc>, +} + #[derive(FromRepr)] pub enum CallHandlerId { Header = 0, @@ -29,12 +44,46 @@ pub enum CallHandlerId { Receipt = 4, } -#[derive(Debug, Default)] +#[derive(Debug, Default, Serialize, Deserialize)] pub struct CallContractHandler { key_set: HashSet, } -impl SyscallHandler for CallContractHandler { +impl SyscallHandlerWrapper { + pub fn new() -> Self { + Self { + syscall_handler: Rc::new(RwLock::new(SyscallHandler::default())), + } + } + pub fn set_syscall_ptr(&self, syscall_ptr: Relocatable) { + let mut syscall_handler = self.syscall_handler.write().unwrap(); + syscall_handler.syscall_ptr = Some(syscall_ptr); + } + + pub fn syscall_ptr(&self) -> Option { + let syscall_handler = self.syscall_handler.read().unwrap(); + syscall_handler.syscall_ptr + } + + pub fn execute_syscall(&mut self, vm: &mut VirtualMachine, syscall_ptr: Relocatable) -> Result<(), HintError> { + let mut syscall_handler = self.syscall_handler.write().unwrap(); + let ptr = &mut syscall_handler + .syscall_ptr + .ok_or(HintError::CustomHint(Box::from("syscall_ptr is None")))?; + + assert_eq!(*ptr, syscall_ptr); + + match SyscallSelector::try_from(felt_from_ptr(vm, ptr)?)? { + SyscallSelector::CallContract => run_handler(&mut syscall_handler.call_contract_handler, ptr, vm), + }?; + + syscall_handler.syscall_ptr = Some(*ptr); + + Ok(()) + } +} + +impl traits::SyscallHandler for CallContractHandler { type Request = CallContractRequest; type Response = CallContractResponse; @@ -69,25 +118,27 @@ impl SyscallHandler for CallContractHandler { let key = header::HeaderCallHandler::derive_key(vm, &mut calldata)?; let function_id = header::HeaderCallHandler::derive_id(request.selector)?; println!("key: {:?}, function_id: {:?}", key, function_id); - let result = header::HeaderCallHandler::handle(key, function_id)?; + let result = header::HeaderCallHandler::handle(key.clone(), function_id)?; result.to_memory(vm, retdata_end)?; retdata_end += ::CallHandlerResult::n_fields(); + self.key_set.insert(DryRunKey::Header(key)); } CallHandlerId::Account => { let key = account::AccountCallHandler::derive_key(vm, &mut calldata)?; let function_id = account::AccountCallHandler::derive_id(request.selector)?; println!("key: {:?}, function_id: {:?}", key, function_id); - let result = account::AccountCallHandler::handle(key, function_id)?; + let result = account::AccountCallHandler::handle(key.clone(), function_id)?; result.to_memory(vm, retdata_end)?; retdata_end += ::CallHandlerResult::n_fields(); + self.key_set.insert(DryRunKey::Account(key)); } CallHandlerId::Storage => { let key = storage::StorageCallHandler::derive_key(vm, &mut calldata)?; let function_id = storage::StorageCallHandler::derive_id(request.selector)?; - println!("key: {:?}, function_id: {:?}", key, function_id); - let result = storage::StorageCallHandler::handle(key, function_id)?; + let result = storage::StorageCallHandler::handle(key.clone(), function_id)?; result.to_memory(vm, retdata_end)?; retdata_end += ::CallHandlerResult::n_fields(); + self.key_set.insert(DryRunKey::Storage(key)); } _ => {} } @@ -117,6 +168,7 @@ impl TryFrom for CallHandlerId { } #[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[serde(rename_all = "lowercase")] enum DryRunKey { Account(account::Key), Header(header::Key), diff --git a/cairo_vm_hints/src/syscall_handler/evm/dryrun/storage.rs b/cairo_vm_hints/src/syscall_handler/evm/dryrun/storage.rs index acdcf3e3..c9dc3469 100644 --- a/cairo_vm_hints/src/syscall_handler/evm/dryrun/storage.rs +++ b/cairo_vm_hints/src/syscall_handler/evm/dryrun/storage.rs @@ -1,7 +1,6 @@ use crate::syscall_handler::{ traits::CallHandler, utils::{SyscallExecutionError, SyscallResult}, - Relocatable, VirtualMachine, }; use crate::{ cairo_types::{ @@ -18,7 +17,11 @@ use alloy::{ primitives::{Address, BlockNumber, ChainId, StorageKey, StorageValue}, transports::http::reqwest::Url, }; -use cairo_vm::{vm::errors::memory_errors::MemoryError, Felt252}; +use cairo_vm::{ + types::relocatable::Relocatable, + vm::{errors::memory_errors::MemoryError, vm_core::VirtualMachine}, + Felt252, +}; use serde::{Deserialize, Serialize}; use std::env; @@ -88,7 +91,7 @@ impl CairoType for CairoKey { } } -#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] pub struct Key { chain_id: ChainId, block_number: BlockNumber, diff --git a/cairo_vm_hints/src/syscall_handler/mod.rs b/cairo_vm_hints/src/syscall_handler/mod.rs index fbc17299..90a5ffbf 100644 --- a/cairo_vm_hints/src/syscall_handler/mod.rs +++ b/cairo_vm_hints/src/syscall_handler/mod.rs @@ -3,59 +3,4 @@ pub mod starknet; pub mod traits; pub mod utils; -use cairo_vm::{ - types::relocatable::Relocatable, - vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, -}; -use std::{rc::Rc, sync::RwLock}; -use utils::{felt_from_ptr, run_handler, SyscallSelector}; - pub(crate) const RPC: &str = "RPC"; - -/// SyscallHandler implementation for execution of system calls in the StarkNet OS -#[derive(Debug, Default)] -pub struct HDPSyscallHandler { - syscall_ptr: Option, - call_contract_handler: evm::dryrun::CallContractHandler, -} - -/// SyscallHandler is wrapped in Rc> in order -/// to clone the reference when entering and exiting vm scopes -#[derive(Debug, Clone, Default)] -pub struct SyscallHandlerWrapper { - pub syscall_handler: Rc>, -} - -impl SyscallHandlerWrapper { - pub fn new() -> Self { - Self { - syscall_handler: Rc::new(RwLock::new(HDPSyscallHandler::default())), - } - } - pub fn set_syscall_ptr(&self, syscall_ptr: Relocatable) { - let mut syscall_handler = self.syscall_handler.write().unwrap(); - syscall_handler.syscall_ptr = Some(syscall_ptr); - } - - pub fn syscall_ptr(&self) -> Option { - let syscall_handler = self.syscall_handler.read().unwrap(); - syscall_handler.syscall_ptr - } - - pub fn execute_syscall(&mut self, vm: &mut VirtualMachine, syscall_ptr: Relocatable) -> Result<(), HintError> { - let mut syscall_handler = self.syscall_handler.write().unwrap(); - let ptr = &mut syscall_handler - .syscall_ptr - .ok_or(HintError::CustomHint(Box::from("syscall_ptr is None")))?; - - assert_eq!(*ptr, syscall_ptr); - - match SyscallSelector::try_from(felt_from_ptr(vm, ptr)?)? { - SyscallSelector::CallContract => run_handler(&mut syscall_handler.call_contract_handler, ptr, vm), - }?; - - syscall_handler.syscall_ptr = Some(*ptr); - - Ok(()) - } -}