From f7102e3509f684ca25122c4bd292a671f269804c Mon Sep 17 00:00:00 2001 From: Bartosz Nowak Date: Wed, 11 Dec 2024 18:41:07 +0100 Subject: [PATCH] key set --- cairo_vm_hints/src/hint_processor/mod.rs | 3 +- .../src/syscall_handler/call_contract.rs | 80 --------------- .../src/syscall_handler/evm/dryrun/account.rs | 3 +- .../src/syscall_handler/evm/dryrun/header.rs | 5 +- .../src/syscall_handler/evm/dryrun/mod.rs | 98 ++++++++++++++++++- .../src/syscall_handler/evm/dryrun/storage.rs | 3 +- cairo_vm_hints/src/syscall_handler/mod.rs | 19 ++-- cairo_vm_hints/src/syscall_handler/traits.rs | 10 +- cairo_vm_hints/src/syscall_handler/utils.rs | 44 ++------- 9 files changed, 125 insertions(+), 140 deletions(-) delete mode 100644 cairo_vm_hints/src/syscall_handler/call_contract.rs diff --git a/cairo_vm_hints/src/hint_processor/mod.rs b/cairo_vm_hints/src/hint_processor/mod.rs index b0a56d8f..79c42064 100644 --- a/cairo_vm_hints/src/hint_processor/mod.rs +++ b/cairo_vm_hints/src/hint_processor/mod.rs @@ -147,8 +147,7 @@ impl HintProcessorLogic for CustomHintProcessor { if let Some(hint) = hint_data.downcast_ref::() { if let Hint::Starknet(StarknetHint::SystemCall { system }) = hint { let syscall_ptr = get_ptr_from_res_operand(vm, system)?; - let syscall_handler = exec_scopes.get::(vars::scopes::SYSCALL_HANDLER)?; - + let syscall_handler = exec_scopes.get_mut_ref::(vars::scopes::SYSCALL_HANDLER)?; return syscall_handler.execute_syscall(vm, syscall_ptr).map(|_| HintExtension::default()); } else { return self diff --git a/cairo_vm_hints/src/syscall_handler/call_contract.rs b/cairo_vm_hints/src/syscall_handler/call_contract.rs deleted file mode 100644 index 51e4945a..00000000 --- a/cairo_vm_hints/src/syscall_handler/call_contract.rs +++ /dev/null @@ -1,80 +0,0 @@ -use super::{ - evm, - traits::CallHandler, - utils::{felt_from_ptr, SyscallExecutionError, SyscallHandler, SyscallResult, WriteResponseResult}, -}; -use crate::cairo_types::{ - new_syscalls::{CallContractRequest, CallContractResponse}, - traits::CairoType, -}; -use cairo_vm::{types::relocatable::Relocatable, vm::vm_core::VirtualMachine}; - -pub struct CallContractHandler; - -impl SyscallHandler for CallContractHandler { - type Request = CallContractRequest; - type Response = CallContractResponse; - - fn read_request(vm: &VirtualMachine, ptr: &mut Relocatable) -> SyscallResult { - let ret = Self::Request::from_memory(vm, *ptr)?; - *ptr = (*ptr + Self::Request::cairo_size())?; - Ok(ret) - } - - fn execute(request: Self::Request, vm: &mut VirtualMachine) -> SyscallResult { - let mut calldata = request.calldata_start; - - let call_handler_id = evm::dryrun::CallHandlerId::try_from(request.contract_address)?; - - let segment_index = felt_from_ptr(vm, &mut calldata)?; - let offset = felt_from_ptr(vm, &mut calldata)?; - - let _memorizer = Relocatable::from(( - segment_index - .try_into() - .map_err(|e| SyscallExecutionError::InternalError(format!("{}", e).into()))?, - offset - .try_into() - .map_err(|e| SyscallExecutionError::InternalError(format!("{}", e).into()))?, - )); - - let retdata_start = vm.add_temporary_segment(); - let mut retdata_end = retdata_start; - - match call_handler_id { - evm::dryrun::CallHandlerId::Header => { - let key = evm::dryrun::header::HeaderCallHandler::derive_key(vm, &mut calldata)?; - let function_id = evm::dryrun::header::HeaderCallHandler::derive_id(request.selector)?; - println!("key: {:?}, function_id: {:?}", key, function_id); - let result = evm::dryrun::header::HeaderCallHandler::handle(key, function_id)?; - result.to_memory(vm, retdata_end)?; - retdata_end += ::CallHandlerResult::n_fields(); - } - evm::dryrun::CallHandlerId::Account => { - let key = evm::dryrun::account::AccountCallHandler::derive_key(vm, &mut calldata)?; - let function_id = evm::dryrun::account::AccountCallHandler::derive_id(request.selector)?; - println!("key: {:?}, function_id: {:?}", key, function_id); - let result = evm::dryrun::account::AccountCallHandler::handle(key, function_id)?; - result.to_memory(vm, retdata_end)?; - retdata_end += ::CallHandlerResult::n_fields(); - } - evm::dryrun::CallHandlerId::Storage => { - let key = evm::dryrun::storage::StorageCallHandler::derive_key(vm, &mut calldata)?; - let function_id = evm::dryrun::storage::StorageCallHandler::derive_id(request.selector)?; - println!("key: {:?}, function_id: {:?}", key, function_id); - let result = evm::dryrun::storage::StorageCallHandler::handle(key, function_id)?; - result.to_memory(vm, retdata_end)?; - retdata_end += ::CallHandlerResult::n_fields(); - } - _ => {} - } - - Ok(Self::Response { retdata_start, retdata_end }) - } - - fn write_response(response: Self::Response, vm: &mut VirtualMachine, ptr: &mut Relocatable) -> WriteResponseResult { - response.to_memory(vm, *ptr)?; - *ptr = (*ptr + Self::Response::cairo_size())?; - 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 c23994bf..70c731c1 100644 --- a/cairo_vm_hints/src/syscall_handler/evm/dryrun/account.rs +++ b/cairo_vm_hints/src/syscall_handler/evm/dryrun/account.rs @@ -19,6 +19,7 @@ use alloy::{ transports::http::reqwest::Url, }; use cairo_vm::{vm::errors::memory_errors::MemoryError, Felt252}; +use serde::{Deserialize, Serialize}; use std::env; pub struct AccountCallHandler; @@ -76,7 +77,7 @@ impl CairoType for CairoKey { } } -#[derive(Debug)] +#[derive(Debug, 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 126d300b..e9368c04 100644 --- a/cairo_vm_hints/src/syscall_handler/evm/dryrun/header.rs +++ b/cairo_vm_hints/src/syscall_handler/evm/dryrun/header.rs @@ -19,6 +19,7 @@ use alloy::{ transports::http::reqwest::Url, }; use cairo_vm::{vm::errors::memory_errors::MemoryError, Felt252}; +use serde::{Deserialize, Serialize}; use std::env; pub struct HeaderCallHandler; @@ -51,7 +52,7 @@ impl CallHandler for HeaderCallHandler { } } -#[derive(Debug)] +#[derive(Debug, Serialize, Deserialize)] pub struct CairoKey { chain_id: Felt252, block_number: Felt252, @@ -74,7 +75,7 @@ impl CairoType for CairoKey { } } -#[derive(Debug)] +#[derive(Debug, 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 48b0d10f..9573322e 100644 --- a/cairo_vm_hints/src/syscall_handler/evm/dryrun/mod.rs +++ b/cairo_vm_hints/src/syscall_handler/evm/dryrun/mod.rs @@ -5,8 +5,19 @@ pub mod receipt; pub mod storage; pub mod transaction; -use crate::syscall_handler::utils::SyscallExecutionError; -use cairo_vm::Felt252; +use crate::cairo_types::traits::CairoType; +use crate::syscall_handler::traits::CallHandler; +use crate::{ + cairo_types::new_syscalls::{CallContractRequest, CallContractResponse}, + syscall_handler::{ + traits::SyscallHandler, + utils::{felt_from_ptr, SyscallExecutionError, SyscallResult, WriteResponseResult}, + }, +}; +use cairo_vm::{types::relocatable::Relocatable, vm::vm_core::VirtualMachine, Felt252}; +use serde::{Deserialize, Serialize}; +use serde_json::Value; +use std::{collections::HashSet, hash::Hash, marker::PhantomData}; use strum_macros::FromRepr; #[derive(FromRepr)] @@ -18,6 +29,79 @@ pub enum CallHandlerId { Receipt = 4, } +#[derive(Debug, Default)] +pub struct CallContractHandler { + key_set: HashSet, +} + +impl SyscallHandler for CallContractHandler { + type Request = CallContractRequest; + type Response = CallContractResponse; + + fn read_request(&mut self, vm: &VirtualMachine, ptr: &mut Relocatable) -> SyscallResult { + let ret = Self::Request::from_memory(vm, *ptr)?; + *ptr = (*ptr + Self::Request::cairo_size())?; + Ok(ret) + } + + fn execute(&mut self, request: Self::Request, vm: &mut VirtualMachine) -> SyscallResult { + let mut calldata = request.calldata_start; + + let call_handler_id = CallHandlerId::try_from(request.contract_address)?; + + let segment_index = felt_from_ptr(vm, &mut calldata)?; + let offset = felt_from_ptr(vm, &mut calldata)?; + + let _memorizer = Relocatable::from(( + segment_index + .try_into() + .map_err(|e| SyscallExecutionError::InternalError(format!("{}", e).into()))?, + offset + .try_into() + .map_err(|e| SyscallExecutionError::InternalError(format!("{}", e).into()))?, + )); + + let retdata_start = vm.add_temporary_segment(); + let mut retdata_end = retdata_start; + + match call_handler_id { + CallHandlerId::Header => { + 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)?; + result.to_memory(vm, retdata_end)?; + retdata_end += ::CallHandlerResult::n_fields(); + } + 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)?; + result.to_memory(vm, retdata_end)?; + retdata_end += ::CallHandlerResult::n_fields(); + } + 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)?; + result.to_memory(vm, retdata_end)?; + retdata_end += ::CallHandlerResult::n_fields(); + } + _ => {} + } + + Ok(Self::Response { retdata_start, retdata_end }) + } + + fn write_response(&mut self, response: Self::Response, vm: &mut VirtualMachine, ptr: &mut Relocatable) -> WriteResponseResult { + response.to_memory(vm, *ptr)?; + *ptr = (*ptr + Self::Response::cairo_size())?; + Ok(()) + } +} + impl TryFrom for CallHandlerId { type Error = SyscallExecutionError; fn try_from(value: Felt252) -> Result { @@ -31,3 +115,13 @@ impl TryFrom for CallHandlerId { }) } } + +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Hash)] +enum DryRunKey { + Account(account::Key), + Header(header::Key), + Storage(storage::Key), +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct DryRunKeySet(HashSet); 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 3e218ed3..acdcf3e3 100644 --- a/cairo_vm_hints/src/syscall_handler/evm/dryrun/storage.rs +++ b/cairo_vm_hints/src/syscall_handler/evm/dryrun/storage.rs @@ -19,6 +19,7 @@ use alloy::{ transports::http::reqwest::Url, }; use cairo_vm::{vm::errors::memory_errors::MemoryError, Felt252}; +use serde::{Deserialize, Serialize}; use std::env; pub struct StorageCallHandler; @@ -87,7 +88,7 @@ impl CairoType for CairoKey { } } -#[derive(Debug)] +#[derive(Debug, 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 181cf4ae..fbc17299 100644 --- a/cairo_vm_hints/src/syscall_handler/mod.rs +++ b/cairo_vm_hints/src/syscall_handler/mod.rs @@ -1,4 +1,3 @@ -pub mod call_contract; pub mod evm; pub mod starknet; pub mod traits; @@ -8,35 +7,29 @@ use cairo_vm::{ types::relocatable::Relocatable, vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, }; -use call_contract::CallContractHandler; 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)] +#[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)] +#[derive(Debug, Clone, Default)] pub struct SyscallHandlerWrapper { pub syscall_handler: Rc>, } -impl Default for SyscallHandlerWrapper { - fn default() -> Self { - Self::new() - } -} - impl SyscallHandlerWrapper { pub fn new() -> Self { Self { - syscall_handler: Rc::new(RwLock::new(HDPSyscallHandler { syscall_ptr: None })), + syscall_handler: Rc::new(RwLock::new(HDPSyscallHandler::default())), } } pub fn set_syscall_ptr(&self, syscall_ptr: Relocatable) { @@ -49,7 +42,7 @@ impl SyscallHandlerWrapper { syscall_handler.syscall_ptr } - pub fn execute_syscall(&self, vm: &mut VirtualMachine, syscall_ptr: Relocatable) -> Result<(), HintError> { + 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 @@ -58,7 +51,7 @@ impl SyscallHandlerWrapper { assert_eq!(*ptr, syscall_ptr); match SyscallSelector::try_from(felt_from_ptr(vm, ptr)?)? { - SyscallSelector::CallContract => run_handler::(ptr, vm), + SyscallSelector::CallContract => run_handler(&mut syscall_handler.call_contract_handler, ptr, vm), }?; syscall_handler.syscall_ptr = Some(*ptr); diff --git a/cairo_vm_hints/src/syscall_handler/traits.rs b/cairo_vm_hints/src/syscall_handler/traits.rs index 9ad8f998..d8133ba6 100644 --- a/cairo_vm_hints/src/syscall_handler/traits.rs +++ b/cairo_vm_hints/src/syscall_handler/traits.rs @@ -1,8 +1,16 @@ use crate::cairo_types::traits::CairoType; -use super::utils::SyscallResult; +use super::utils::{SyscallResult, WriteResponseResult}; use cairo_vm::{types::relocatable::Relocatable, vm::vm_core::VirtualMachine, Felt252}; +pub trait SyscallHandler { + type Request; + type Response; + fn read_request(&mut self, vm: &VirtualMachine, ptr: &mut Relocatable) -> SyscallResult; + fn execute(&mut self, request: Self::Request, vm: &mut VirtualMachine) -> SyscallResult; + fn write_response(&mut self, response: Self::Response, vm: &mut VirtualMachine, ptr: &mut Relocatable) -> WriteResponseResult; +} + pub trait CallHandler { type Key; type Id; diff --git a/cairo_vm_hints/src/syscall_handler/utils.rs b/cairo_vm_hints/src/syscall_handler/utils.rs index d5f4db4d..a44223aa 100644 --- a/cairo_vm_hints/src/syscall_handler/utils.rs +++ b/cairo_vm_hints/src/syscall_handler/utils.rs @@ -11,6 +11,8 @@ use cairo_vm::{ }; use thiserror::Error; +use super::traits::SyscallHandler; + #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub enum SyscallSelector { CallContract, @@ -128,37 +130,6 @@ impl From for SyscallExecutionError { pub type SyscallResult = Result; pub type WriteResponseResult = SyscallResult<()>; -// Common structs. - -#[derive(Debug, Eq, PartialEq)] -pub struct EmptyRequest; - -#[derive(Debug, Eq, PartialEq)] -pub struct EmptyResponse; - -#[derive(Debug)] -pub struct ReadOnlySegment { - pub start_ptr: Relocatable, - pub length: usize, -} - -pub fn write_segment(vm: &mut VirtualMachine, ptr: &mut Relocatable, segment: ReadOnlySegment) -> SyscallResult<()> { - write_maybe_relocatable(vm, ptr, segment.start_ptr)?; - let segment_end_ptr = (segment.start_ptr + segment.length)?; - write_maybe_relocatable(vm, ptr, segment_end_ptr)?; - - Ok(()) -} - -#[allow(async_fn_in_trait)] -pub trait SyscallHandler { - type Request; - type Response; - fn read_request(vm: &VirtualMachine, ptr: &mut Relocatable) -> SyscallResult; - fn execute(request: Self::Request, vm: &mut VirtualMachine) -> SyscallResult; - fn write_response(response: Self::Response, vm: &mut VirtualMachine, ptr: &mut Relocatable) -> WriteResponseResult; -} - fn write_failure(gas_counter: Felt252, error_data: Vec, vm: &mut VirtualMachine, ptr: &mut Relocatable) -> SyscallResult<()> { write_felt(vm, ptr, gas_counter)?; // 1 to indicate failure. @@ -177,18 +148,15 @@ fn write_failure(gas_counter: Felt252, error_data: Vec, vm: &mut Virtua pub const OUT_OF_GAS_ERROR: &str = "0x000000000000000000000000000000000000000000004f7574206f6620676173"; -pub fn run_handler(syscall_ptr: &mut Relocatable, vm: &mut VirtualMachine) -> Result<(), HintError> -where - SH: SyscallHandler, -{ +pub fn run_handler(syscall_handler: &mut impl SyscallHandler, syscall_ptr: &mut Relocatable, vm: &mut VirtualMachine) -> Result<(), HintError> { let remaining_gas = felt_from_ptr(vm, syscall_ptr)?; - let request = SH::read_request(vm, syscall_ptr)?; - let syscall_result = SH::execute(request, vm); + let request = syscall_handler.read_request(vm, syscall_ptr)?; + let syscall_result = syscall_handler.execute(request, vm); match syscall_result { Ok(response) => { write_felt(vm, syscall_ptr, remaining_gas)?; write_felt(vm, syscall_ptr, Felt252::ZERO)?; - SH::write_response(response, vm, syscall_ptr)? + syscall_handler.write_response(response, vm, syscall_ptr)? } Err(SyscallExecutionError::SyscallError { error_data: data }) => { write_failure(Felt252::ZERO, data, vm, syscall_ptr)?;