Skip to content
This repository was archived by the owner on Jul 22, 2024. It is now read-only.

Add storage_write syscall #345

Merged
merged 4 commits into from
Apr 18, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/core/errors/syscall_handler_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use cairo_rs::{
hint_errors::HintError, memory_errors::MemoryError, vm_errors::VirtualMachineError,
},
};
use felt::Felt252;
use thiserror::Error;

#[derive(Debug, Error)]
Expand All @@ -21,6 +22,10 @@ pub enum SyscallHandlerError {
FailToComputeHash,
#[error("Expected DesployRequestStruct")]
ExpectedDeployRequestStruct,
#[error("Expected StorageWriteSyscall")]
ExpectedStorageWriteSyscall,
#[error("Unsopported address domain: {0}")]
UnsopportedAddressDomain(Felt252),
#[error("Expected GetCallerAddressRequest")]
ExpectedGetCallerAddressRequest,
#[error("Expected SendMessageToL1")]
Expand Down
113 changes: 112 additions & 1 deletion src/core/syscalls/business_logic_syscall_handler.rs
Original file line number Diff line number Diff line change
@@ -1 +1,112 @@
pub struct BusinessLogicSyscallHandler;
#![allow(dead_code)]

use cairo_rs::{types::relocatable::Relocatable, vm::vm_core::VirtualMachine};
use felt::Felt252;

use crate::{
business_logic::{
fact_state::state::ExecutionResourcesManager,
state::{
contract_storage_state::ContractStorageState,
state_api::{State, StateReader},
},
},
core::errors::syscall_handler_errors::SyscallHandlerError,
utils::Address,
};

use super::{
syscall_handler::SyscallHandler,
syscall_info::get_syscall_size_from_name,
syscall_request::{FromPtr, SyscallRequest},
syscall_response::SyscallResponse,
};

pub struct BusinessLogicSyscallHandler<'a, T: Default + State + StateReader> {
pub(crate) resources_manager: ExecutionResourcesManager,
pub(crate) expected_syscall_ptr: Relocatable,
pub(crate) starknet_storage_state: ContractStorageState<'a, T>,
}

impl<'a, T: Default + State + StateReader> BusinessLogicSyscallHandler<'a, T> {
fn new(
state: &'a mut T,
contract_address: Address,
resources_manager: ExecutionResourcesManager,
expected_syscall_ptr: Relocatable,
) -> Self {
let starknet_storage_state = ContractStorageState::new(state, contract_address);
Self {
resources_manager,
expected_syscall_ptr,
starknet_storage_state,
}
}

fn increment_syscall_count(&mut self, syscall_name: &str) {
self.resources_manager
.increment_syscall_counter(syscall_name, 1);
}

fn _storage_write(&mut self, key: Felt252, value: Felt252) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please rename the function to syscall_storage_write to avoid using underscore. I just this in order to keep consistency with the changes to this things that we already did in main.

self.starknet_storage_state.write(&key.to_le_bytes(), value)
}
}

impl<'a, T: Default + State + StateReader> SyscallHandler for BusinessLogicSyscallHandler<'a, T> {
#[allow(irrefutable_let_patterns)]
fn storage_write(
&mut self,
vm: &mut VirtualMachine,
syscall_ptr: Relocatable,
remaining_gas: u64,
) -> Result<SyscallResponse, SyscallHandlerError> {
let request = if let SyscallRequest::StorageWrite(request) =
self.read_and_validate_syscall_request("storage_write", vm, syscall_ptr)?
{
request
} else {
return Err(SyscallHandlerError::ExpectedStorageWriteSyscall);
};

if request.reserved != 0.into() {
return Err(SyscallHandlerError::UnsopportedAddressDomain(
request.reserved,
));
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't the call to _storage_write() missing here?

Ok(SyscallResponse {
gas: remaining_gas,
body: None,
})
}

fn read_and_validate_syscall_request(
&mut self,
syscall_name: &str,
vm: &VirtualMachine,
syscall_ptr: Relocatable,
) -> Result<SyscallRequest, SyscallHandlerError> {
self.increment_syscall_count(syscall_name);
let syscall_request = self.read_syscall_request(syscall_name, vm, syscall_ptr)?;

self.expected_syscall_ptr.offset += get_syscall_size_from_name(syscall_name);
Ok(syscall_request)
}

fn read_syscall_request(
&self,
syscall_name: &str,
vm: &VirtualMachine,
syscall_ptr: Relocatable,
) -> Result<SyscallRequest, SyscallHandlerError> {
match syscall_name {
"storage_write" => {
super::syscall_request::StorageWriteRequest::from_ptr(vm, syscall_ptr)
}
_ => Err(SyscallHandlerError::UnknownSyscall(
syscall_name.to_string(),
)),
}
}
}
39 changes: 38 additions & 1 deletion src/core/syscalls/syscall_handler.rs
Original file line number Diff line number Diff line change
@@ -1 +1,38 @@
pub trait SyscallHandler {}
use cairo_rs::{types::relocatable::Relocatable, vm::vm_core::VirtualMachine};

use crate::core::errors::syscall_handler_errors::SyscallHandlerError;

use super::{
syscall_request::{FromPtr, StorageWriteRequest, SyscallRequest},
syscall_response::SyscallResponse,
};

pub(crate) trait SyscallHandler {
fn read_and_validate_syscall_request(
&mut self,
syscall_name: &str,
vm: &VirtualMachine,
syscall_ptr: Relocatable,
) -> Result<SyscallRequest, SyscallHandlerError>;

fn storage_write(
&mut self,
vm: &mut VirtualMachine,
syscall_ptr: Relocatable,
remaining_gas: u64,
) -> Result<SyscallResponse, SyscallHandlerError>;

fn read_syscall_request(
&self,
syscall_name: &str,
vm: &VirtualMachine,
syscall_ptr: Relocatable,
) -> Result<SyscallRequest, SyscallHandlerError> {
match syscall_name {
"storage_write" => StorageWriteRequest::from_ptr(vm, syscall_ptr),
_ => Err(SyscallHandlerError::UnknownSyscall(
syscall_name.to_string(),
)),
}
}
}
48 changes: 46 additions & 2 deletions src/core/syscalls/syscall_request.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,46 @@
#[allow(unused)]
pub(crate) enum SyscallRequest {}
use cairo_rs::{types::relocatable::Relocatable, vm::vm_core::VirtualMachine};
use felt::Felt252;

use crate::{core::errors::syscall_handler_errors::SyscallHandlerError, utils::get_big_int};

pub(crate) enum SyscallRequest {
StorageWrite(StorageWriteRequest),
}

#[derive(Clone, Debug, PartialEq)]
pub(crate) struct StorageWriteRequest {
pub(crate) reserved: Felt252,
pub(crate) key: Felt252,
pub(crate) value: Felt252,
}

impl From<StorageWriteRequest> for SyscallRequest {
fn from(storage_write_request: StorageWriteRequest) -> SyscallRequest {
SyscallRequest::StorageWrite(storage_write_request)
}
}

pub(crate) trait FromPtr {
fn from_ptr(
vm: &VirtualMachine,
syscall_ptr: Relocatable,
) -> Result<SyscallRequest, SyscallHandlerError>;
}

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())
}
}
4 changes: 2 additions & 2 deletions src/core/syscalls/syscall_response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pub(crate) enum ResponseBody {}
#[allow(unused)]
pub(crate) struct SyscallResponse {
/// The amount of gas left after the syscall execution.
gas: u64,
pub(crate) gas: u64,
/// Syscall specific response fields.
body: Option<ResponseBody>,
pub(crate) body: Option<ResponseBody>,
}