Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(blockifier): share get_block_hash syscall code between native and casm #2107

Merged
merged 1 commit into from
Nov 18, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 2 additions & 31 deletions crates/blockifier/src/execution/native/syscall_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ use starknet_api::transaction::fields::{Calldata, ContractAddressSalt};
use starknet_api::transaction::{EventContent, EventData, EventKey, L2ToL1Payload};
use starknet_types_core::felt::Felt;

use crate::abi::constants;
use crate::execution::call_info::{
CallInfo,
MessageToL1,
Expand All @@ -53,13 +52,12 @@ use crate::execution::errors::EntryPointExecutionError;
use crate::execution::execution_utils::execute_deployment;
use crate::execution::native::utils::{calculate_resource_bounds, default_tx_v2_info};
use crate::execution::secp;
use crate::execution::syscalls::exceeds_event_size_limit;
use crate::execution::syscalls::hint_processor::{
SyscallExecutionError,
BLOCK_NUMBER_OUT_OF_RANGE_ERROR,
INVALID_INPUT_LENGTH_ERROR,
OUT_OF_GAS_ERROR,
};
use crate::execution::syscalls::{exceeds_event_size_limit, syscall_base};
use crate::state::state_api::State;
use crate::transaction::objects::TransactionInfo;

Expand Down Expand Up @@ -276,34 +274,7 @@ impl<'state> StarknetSyscallHandler for &mut NativeSyscallHandler<'state> {
) -> SyscallResult<Felt> {
self.pre_execute_syscall(remaining_gas, 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
{
// `panic` is unreachable in this case, also this is covered by tests so we can safely
// unwrap
let out_of_range_felt = Felt::from_hex(BLOCK_NUMBER_OUT_OF_RANGE_ERROR)
.expect("Converting BLOCK_NUMBER_OUT_OF_RANGE_ERROR to Felt should not fail.");
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) {
match syscall_base::get_block_hash_base(self.context, block_number, self.state) {
Ok(value) => Ok(value),
Err(e) => Err(self.handle_error(remaining_gas, e.into())),
}
Expand Down
34 changes: 7 additions & 27 deletions crates/blockifier/src/execution/syscalls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,7 @@ use self::hint_processor::{
EmitEventError,
SyscallExecutionError,
SyscallHintProcessor,
BLOCK_NUMBER_OUT_OF_RANGE_ERROR,
};
use crate::abi::constants;
use crate::execution::call_info::{MessageToL1, OrderedEvent, OrderedL2ToL1Message};
use crate::execution::deprecated_syscalls::DeprecatedSyscallSelector;
use crate::execution::entry_point::{CallEntryPoint, CallType, ConstructorContext};
Expand All @@ -41,16 +39,17 @@ use crate::execution::execution_utils::{
ReadOnlySegment,
};
use crate::execution::syscalls::hint_processor::{INVALID_INPUT_LENGTH_ERROR, OUT_OF_GAS_ERROR};
use crate::execution::syscalls::syscall_base::SyscallResult;
use crate::transaction::account_transaction::is_cairo1;
use crate::versioned_constants::{EventLimits, VersionedConstants};

pub mod hint_processor;
mod secp;
pub mod syscall_base;

#[cfg(test)]
pub mod syscall_tests;

pub type SyscallResult<T> = Result<T, SyscallExecutionError>;
pub type WriteResponseResult = SyscallResult<()>;

pub type SyscallSelector = DeprecatedSyscallSelector;
Expand Down Expand Up @@ -392,30 +391,11 @@ pub fn get_block_hash(
syscall_handler: &mut SyscallHintProcessor<'_>,
_remaining_gas: &mut u64,
) -> SyscallResult<GetBlockHashResponse> {
if syscall_handler.is_validate_mode() {
return Err(SyscallExecutionError::InvalidSyscallInExecutionMode {
syscall_name: "get_block_hash".to_string(),
execution_mode: syscall_handler.execution_mode(),
});
}

let requested_block_number = request.block_number.0;
let current_block_number =
syscall_handler.context.tx_context.block_context.block_info.block_number.0;

if current_block_number < constants::STORED_BLOCK_HASH_BUFFER
|| requested_block_number > current_block_number - constants::STORED_BLOCK_HASH_BUFFER
{
let out_of_range_error =
Felt::from_hex(BLOCK_NUMBER_OUT_OF_RANGE_ERROR).map_err(SyscallExecutionError::from)?;
return Err(SyscallExecutionError::SyscallError { error_data: vec![out_of_range_error] });
}

let key = StorageKey::try_from(Felt::from(requested_block_number))?;
let block_hash_contract_address =
ContractAddress::try_from(Felt::from(constants::BLOCK_HASH_CONTRACT_ADDRESS))?;
let block_hash =
BlockHash(syscall_handler.state.get_storage_at(block_hash_contract_address, key)?);
let block_hash = BlockHash(syscall_base::get_block_hash_base(
syscall_handler.context,
request.block_number.0,
syscall_handler.state,
)?);
Ok(GetBlockHashResponse { block_hash })
}

Expand Down
44 changes: 44 additions & 0 deletions crates/blockifier/src/execution/syscalls/syscall_base.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/// This file is for sharing common logic between Native and Casm syscalls implementations.
use starknet_api::core::ContractAddress;
use starknet_api::state::StorageKey;
use starknet_types_core::felt::Felt;

use crate::abi::constants;
use crate::execution::common_hints::ExecutionMode;
use crate::execution::entry_point::EntryPointExecutionContext;
use crate::execution::syscalls::hint_processor::{
SyscallExecutionError,
BLOCK_NUMBER_OUT_OF_RANGE_ERROR,
};
use crate::state::state_api::State;

pub type SyscallResult<T> = Result<T, SyscallExecutionError>;

pub fn get_block_hash_base(
context: &EntryPointExecutionContext,
requested_block_number: u64,
state: &dyn State,
) -> SyscallResult<Felt> {
let execution_mode = context.execution_mode;
if execution_mode == ExecutionMode::Validate {
return Err(SyscallExecutionError::InvalidSyscallInExecutionMode {
syscall_name: "get_block_hash".to_string(),
execution_mode,
});
}

let current_block_number = context.tx_context.block_context.block_info.block_number.0;

if current_block_number < constants::STORED_BLOCK_HASH_BUFFER
|| requested_block_number > current_block_number - constants::STORED_BLOCK_HASH_BUFFER
{
let out_of_range_error = Felt::from_hex(BLOCK_NUMBER_OUT_OF_RANGE_ERROR)
.expect("Converting BLOCK_NUMBER_OUT_OF_RANGE_ERROR to Felt should not fail.");
return Err(SyscallExecutionError::SyscallError { error_data: vec![out_of_range_error] });
}

let key = StorageKey::try_from(Felt::from(requested_block_number))?;
let block_hash_contract_address =
ContractAddress::try_from(Felt::from(constants::BLOCK_HASH_CONTRACT_ADDRESS))?;
Ok(state.get_storage_at(block_hash_contract_address, key)?)
}
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,10 @@ fn negative_flow_block_number_out_of_range(test_contract: FeatureContract) {
..trivial_external_entry_point_new(test_contract)
};

let call_result = entry_point_call.execute_directly(&mut state);
let (actual_error_msg, expected_error_msg) = (
format_panic_data(&call_result.unwrap().execution.retdata.0),
"0x426c6f636b206e756d626572206f7574206f662072616e6765 ('Block number out of range')",
let call_info = entry_point_call.execute_directly(&mut state).unwrap();
assert!(call_info.execution.failed);
assert_eq!(
format_panic_data(&call_info.execution.retdata.0),
"0x426c6f636b206e756d626572206f7574206f662072616e6765 ('Block number out of range')"
);

assert_eq!(actual_error_msg, expected_error_msg);
}
Loading