use cairo_vm::felt::Felt252;
use cairo_vm::{types::relocatable::Relocatable, vm::vm_core::VirtualMachine};
use num_traits::ToPrimitive;
use crate::{
syscalls::syscall_handler_errors::SyscallHandlerError,
utils::{get_big_int, get_integer, get_relocatable, Address},
};
#[allow(unused)]
#[derive(Debug, PartialEq)]
pub(crate) enum SyscallRequest {
EmitEvent(EmitEventRequest),
LibraryCall(LibraryCallRequest),
CallContract(CallContractRequest),
Deploy(DeployRequest),
GetBlockNumber,
GetExecutionInfo,
StorageRead(StorageReadRequest),
StorageWrite(StorageWriteRequest),
SendMessageToL1(SendMessageToL1Request),
GetBlockTimestamp(GetBlockTimestampRequest),
GetBlockHash(GetBlockHashRequest),
ReplaceClass(ReplaceClassRequest),
Keccak(KeccakRequest),
}
#[allow(unused)]
#[derive(Clone, Debug, PartialEq)]
pub(crate) struct GetBlockTimestampRequest {}
#[allow(unused)]
#[derive(Clone, Debug, PartialEq)]
pub(crate) struct DeployRequest {
pub(crate) class_hash: Felt252,
pub(crate) salt: Felt252,
pub(crate) calldata_start: Relocatable,
pub(crate) calldata_end: Relocatable,
pub(crate) deploy_from_zero: usize,
}
#[derive(Clone, Debug, PartialEq)]
pub(crate) struct StorageReadRequest {
pub(crate) key: [u8; 32],
pub(crate) reserved: Felt252,
}
#[derive(Clone, Debug, PartialEq)]
pub(crate) struct EmitEventRequest {
pub(crate) keys_start: Relocatable,
pub(crate) keys_end: Relocatable,
pub(crate) data_start: Relocatable,
pub(crate) data_end: Relocatable,
}
#[derive(Clone, Debug, PartialEq)]
pub(crate) struct CallContractRequest {
pub(crate) selector: Felt252,
pub(crate) contract_address: Address,
pub(crate) calldata_start: Relocatable,
pub(crate) calldata_end: Relocatable,
}
#[derive(Clone, Debug, PartialEq)]
pub(crate) struct LibraryCallRequest {
pub(crate) class_hash: Felt252,
pub(crate) selector: Felt252,
pub(crate) calldata_start: Relocatable,
pub(crate) calldata_end: Relocatable,
}
#[derive(Clone, Debug, PartialEq)]
pub(crate) struct StorageWriteRequest {
pub(crate) reserved: Felt252,
pub(crate) key: Felt252,
pub(crate) value: Felt252,
}
#[derive(Clone, Debug, PartialEq)]
pub(crate) struct SendMessageToL1Request {
pub(crate) to_address: Address,
pub(crate) payload_start: Relocatable,
pub(crate) payload_end: Relocatable,
}
#[derive(Clone, Debug, PartialEq)]
pub(crate) struct GetBlockHashRequest {
pub(crate) block_number: u64,
}
#[allow(unused)]
#[derive(Clone, Debug, PartialEq)]
pub(crate) struct ReplaceClassRequest {
pub(crate) class_hash: Felt252,
}
#[allow(unused)]
#[derive(Clone, Debug, PartialEq)]
pub(crate) struct KeccakRequest {
pub(crate) input_start: Relocatable,
pub(crate) input_end: Relocatable,
}
impl From<ReplaceClassRequest> for SyscallRequest {
fn from(replace_class_request: ReplaceClassRequest) -> SyscallRequest {
SyscallRequest::ReplaceClass(replace_class_request)
}
}
impl From<GetBlockTimestampRequest> for SyscallRequest {
fn from(get_block_timestamp: GetBlockTimestampRequest) -> SyscallRequest {
SyscallRequest::GetBlockTimestamp(get_block_timestamp)
}
}
impl From<EmitEventRequest> for SyscallRequest {
fn from(emit_event_struct: EmitEventRequest) -> SyscallRequest {
SyscallRequest::EmitEvent(emit_event_struct)
}
}
impl From<CallContractRequest> for SyscallRequest {
fn from(call_contract_request: CallContractRequest) -> SyscallRequest {
SyscallRequest::CallContract(call_contract_request)
}
}
impl From<LibraryCallRequest> for SyscallRequest {
fn from(library_call_request: LibraryCallRequest) -> Self {
SyscallRequest::LibraryCall(library_call_request)
}
}
impl From<SendMessageToL1Request> for SyscallRequest {
fn from(syscall: SendMessageToL1Request) -> Self {
SyscallRequest::SendMessageToL1(syscall)
}
}
impl From<StorageWriteRequest> for SyscallRequest {
fn from(storage_write_request: StorageWriteRequest) -> SyscallRequest {
SyscallRequest::StorageWrite(storage_write_request)
}
}
impl From<StorageReadRequest> for SyscallRequest {
fn from(storage_read_request: StorageReadRequest) -> SyscallRequest {
SyscallRequest::StorageRead(storage_read_request)
}
}
impl From<GetBlockHashRequest> for SyscallRequest {
fn from(get_block_hash_request: GetBlockHashRequest) -> SyscallRequest {
SyscallRequest::GetBlockHash(get_block_hash_request)
}
}
impl From<KeccakRequest> for SyscallRequest {
fn from(request: KeccakRequest) -> SyscallRequest {
SyscallRequest::Keccak(request)
}
}
pub(crate) trait FromPtr {
fn from_ptr(
vm: &VirtualMachine,
syscall_ptr: Relocatable,
) -> Result<SyscallRequest, SyscallHandlerError>;
}
impl FromPtr for ReplaceClassRequest {
fn from_ptr(
vm: &VirtualMachine,
syscall_ptr: Relocatable,
) -> Result<SyscallRequest, SyscallHandlerError> {
Ok(ReplaceClassRequest {
class_hash: vm.get_integer(syscall_ptr)?.into_owned(),
}
.into())
}
}
impl FromPtr for GetBlockTimestampRequest {
fn from_ptr(
_vm: &VirtualMachine,
_syscall_ptr: Relocatable,
) -> Result<SyscallRequest, SyscallHandlerError> {
Ok(GetBlockTimestampRequest {}.into())
}
}
impl FromPtr for GetBlockHashRequest {
fn from_ptr(
vm: &VirtualMachine,
syscall_ptr: Relocatable,
) -> Result<SyscallRequest, SyscallHandlerError> {
Ok(GetBlockHashRequest {
block_number: get_big_int(vm, syscall_ptr)?.to_u64().ok_or(
SyscallHandlerError::Conversion("Felt252".to_string(), "u64".to_string()),
)?,
}
.into())
}
}
impl FromPtr for EmitEventRequest {
fn from_ptr(
vm: &VirtualMachine,
syscall_ptr: Relocatable,
) -> Result<SyscallRequest, SyscallHandlerError> {
let keys_start = get_relocatable(vm, syscall_ptr)?;
let keys_end = get_relocatable(vm, &syscall_ptr + 1)?;
let data_start = get_relocatable(vm, &syscall_ptr + 2)?;
let data_end = get_relocatable(vm, &syscall_ptr + 3)?;
Ok(EmitEventRequest {
keys_start,
keys_end,
data_start,
data_end,
}
.into())
}
}
impl FromPtr for StorageReadRequest {
fn from_ptr(
vm: &VirtualMachine,
syscall_ptr: Relocatable,
) -> Result<SyscallRequest, SyscallHandlerError> {
let reserved = get_big_int(vm, syscall_ptr)?;
let key = get_big_int(vm, &syscall_ptr + 1)?.to_be_bytes();
Ok(StorageReadRequest { key, reserved }.into())
}
}
impl FromPtr for DeployRequest {
fn from_ptr(
vm: &VirtualMachine,
syscall_ptr: Relocatable,
) -> Result<SyscallRequest, SyscallHandlerError> {
let class_hash = get_big_int(vm, syscall_ptr)?;
let salt = get_big_int(vm, (syscall_ptr + 1)?)?;
let calldata_start = get_relocatable(vm, (syscall_ptr + 2)?)?;
let calldata_end = get_relocatable(vm, (syscall_ptr + 3)?)?;
let deploy_from_zero = get_integer(vm, (syscall_ptr + 4)?)?;
Ok(SyscallRequest::Deploy(DeployRequest {
class_hash,
salt,
calldata_start,
calldata_end,
deploy_from_zero,
}))
}
}
impl FromPtr for CallContractRequest {
fn from_ptr(
vm: &VirtualMachine,
syscall_ptr: Relocatable,
) -> Result<SyscallRequest, SyscallHandlerError> {
let contract_address = Address(get_big_int(vm, syscall_ptr)?);
let selector = get_big_int(vm, &syscall_ptr + 1)?;
let calldata_start = get_relocatable(vm, &syscall_ptr + 2)?;
let calldata_end = get_relocatable(vm, &syscall_ptr + 3)?;
Ok(CallContractRequest {
selector,
contract_address,
calldata_start,
calldata_end,
}
.into())
}
}
impl FromPtr for LibraryCallRequest {
fn from_ptr(
vm: &VirtualMachine,
syscall_ptr: Relocatable,
) -> Result<SyscallRequest, SyscallHandlerError> {
let class_hash = get_big_int(vm, syscall_ptr)?;
let selector = get_big_int(vm, &syscall_ptr + 1)?;
let calldata_start = get_relocatable(vm, &syscall_ptr + 2)?;
let calldata_end = get_relocatable(vm, &syscall_ptr + 3)?;
Ok(LibraryCallRequest {
class_hash,
selector,
calldata_start,
calldata_end,
}
.into())
}
}
impl FromPtr for SendMessageToL1Request {
fn from_ptr(
vm: &VirtualMachine,
syscall_ptr: Relocatable,
) -> Result<SyscallRequest, SyscallHandlerError> {
let to_address = Address(get_big_int(vm, syscall_ptr)?);
let payload_start = get_relocatable(vm, &syscall_ptr + 1)?;
let payload_end = get_relocatable(vm, &syscall_ptr + 2)?;
Ok(SendMessageToL1Request {
to_address,
payload_start,
payload_end,
}
.into())
}
}
impl FromPtr for StorageWriteRequest {
fn from_ptr(
vm: &VirtualMachine,
syscall_ptr: Relocatable,
) -> Result<SyscallRequest, SyscallHandlerError> {
let reserved = get_big_int(vm, syscall_ptr)?;
let key = get_big_int(vm, &syscall_ptr + 1)?;
let value = get_big_int(vm, &syscall_ptr + 2)?;
Ok(StorageWriteRequest {
reserved,
key,
value,
}
.into())
}
}
impl FromPtr for KeccakRequest {
fn from_ptr(
vm: &VirtualMachine,
syscall_ptr: Relocatable,
) -> Result<SyscallRequest, SyscallHandlerError> {
let input_start = get_relocatable(vm, syscall_ptr)?;
let input_end = get_relocatable(vm, &syscall_ptr + 1)?;
Ok(KeccakRequest {
input_start,
input_end,
}
.into())
}
}