diff --git a/crates/blockifier/src/execution/native/syscall_handler.rs b/crates/blockifier/src/execution/native/syscall_handler.rs index 9676f80fd6..6e58d16431 100644 --- a/crates/blockifier/src/execution/native/syscall_handler.rs +++ b/crates/blockifier/src/execution/native/syscall_handler.rs @@ -11,14 +11,18 @@ use cairo_native::starknet::{ U256, }; use cairo_vm::vm::runners::cairo_runner::ExecutionResources; +use starknet_api::core::ContractAddress; use starknet_api::state::StorageKey; use starknet_types_core::felt::Felt; +use crate::abi::constants; use crate::execution::call_info::{CallInfo, OrderedEvent, OrderedL2ToL1Message, Retdata}; +use crate::execution::common_hints::ExecutionMode; use crate::execution::entry_point::{CallEntryPoint, EntryPointExecutionContext}; use crate::execution::syscalls::hint_processor::{ SyscallCounter, SyscallExecutionError, + BLOCK_NUMBER_OUT_OF_RANGE_ERROR, OUT_OF_GAS_ERROR, }; use crate::execution::syscalls::SyscallSelector; @@ -60,8 +64,8 @@ impl<'state> NativeSyscallHandler<'state> { context, events: Vec::new(), l2_to_l1_messages: Vec::new(), - inner_calls: Vec::new(), syscall_counter: SyscallCounter::new(), + inner_calls: Vec::new(), read_values: Vec::new(), accessed_keys: HashSet::new(), unrecoverable_error: None, @@ -159,10 +163,43 @@ impl<'state> NativeSyscallHandler<'state> { impl<'state> StarknetSyscallHandler for &mut NativeSyscallHandler<'state> { fn get_block_hash( &mut self, - _block_number: u64, - _remaining_gas: &mut u128, + block_number: u64, + remaining_gas: &mut u128, ) -> SyscallResult { - todo!("Implement get_block_hash syscall."); + self.pre_execute_syscall( + remaining_gas, + SyscallSelector::GetBlockHash, + self.context.gas_costs().get_block_hash_gas_cost, + )?; + + if self.context.execution_mode == ExecutionMode::Validate { + let err = SyscallExecutionError::InvalidSyscallInExecutionMode { + syscall_name: "get_block_hash".to_string(), + execution_mode: ExecutionMode::Validate, + }; + return Err(self.handle_error(remaining_gas, err)); + } + + let current_block_number = + self.context.tx_context.block_context.block_info().block_number.0; + if current_block_number < constants::STORED_BLOCK_HASH_BUFFER + || block_number > current_block_number - constants::STORED_BLOCK_HASH_BUFFER + { + let out_of_range_felt = Felt::from_hex(BLOCK_NUMBER_OUT_OF_RANGE_ERROR).unwrap(); + let error = SyscallExecutionError::SyscallError { error_data: vec![out_of_range_felt] }; + return Err(self.handle_error(remaining_gas, error)); + } + + let key = StorageKey::try_from(Felt::from(block_number)) + .map_err(|e| self.handle_error(remaining_gas, e.into()))?; + let block_hash_contract_address = + ContractAddress::try_from(Felt::from(constants::BLOCK_HASH_CONTRACT_ADDRESS)) + .map_err(|e| self.handle_error(remaining_gas, e.into()))?; + + match self.state.get_storage_at(block_hash_contract_address, key) { + Ok(value) => Ok(value), + Err(e) => Err(self.handle_error(remaining_gas, e.into())), + } } fn get_execution_info(&mut self, _remaining_gas: &mut u128) -> SyscallResult { diff --git a/crates/blockifier/src/execution/syscalls/syscall_tests/get_block_hash.rs b/crates/blockifier/src/execution/syscalls/syscall_tests/get_block_hash.rs index bec856d07e..9092f451f9 100644 --- a/crates/blockifier/src/execution/syscalls/syscall_tests/get_block_hash.rs +++ b/crates/blockifier/src/execution/syscalls/syscall_tests/get_block_hash.rs @@ -40,6 +40,10 @@ fn initialize_state(test_contract: FeatureContract) -> (CachedState