Skip to content
This repository has been archived by the owner on Aug 21, 2024. It is now read-only.

Add skeleton for the get_block_hash syscall. #568

Merged
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

Large diffs are not rendered by default.

3,015 changes: 1,564 additions & 1,451 deletions crates/blockifier/feature_contracts/cairo1/compiled/test_contract.sierra.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ mod TestContract {
use array::SpanTrait;
use clone::Clone;
use traits::Into;
use traits::TryInto;
use option::OptionTrait;

const UNEXPECTED_ERROR: felt252 = 'UNEXPECTED ERROR';

Expand Down Expand Up @@ -48,6 +50,11 @@ mod TestContract {
starknet::syscalls::emit_event_syscall(keys.span(), data.span()).unwrap_syscall();
}

#[external]
fn test_get_block_hash(self: @Storage, block_number: u64) -> felt252 {
starknet::syscalls::get_block_hash_syscall(block_number).unwrap_syscall()
}

#[external]
fn test_get_execution_info(
self: @Storage,
Expand Down
8 changes: 8 additions & 0 deletions crates/blockifier/src/abi/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,17 @@ pub const TRANSACTION_GAS_COST: u64 =
pub const CALL_CONTRACT_GAS_COST: u64 = 10 * STEP_GAS_COST + ENTRY_POINT_GAS_COST;
pub const DEPLOY_GAS_COST: u64 = 200 * STEP_GAS_COST + ENTRY_POINT_GAS_COST;
pub const EMIT_EVENT_GAS_COST: u64 = 10 * STEP_GAS_COST;
pub const GET_BLOCK_HASH_GAS_COST: u64 = 50 * STEP_GAS_COST;
pub const GET_EXECUTION_INFO_GAS_COST: u64 = 10 * STEP_GAS_COST;
pub const LIBRARY_CALL_GAS_COST: u64 = CALL_CONTRACT_GAS_COST;
pub const REPLACE_CLASS_GAS_COST: u64 = 50 * STEP_GAS_COST;
pub const SEND_MESSAGE_TO_L1_GAS_COST: u64 = 50 * STEP_GAS_COST;
pub const STORAGE_READ_GAS_COST: u64 = 50 * STEP_GAS_COST;
pub const STORAGE_WRITE_GAS_COST: u64 = 50 * STEP_GAS_COST;

// OS reserved contract addresses.

// This contract stores the block number -> block hash mapping.
// TODO(Arni, 14/6/2023): Replace BLOCK_HASH_CONSTANT_ADDRESS with a lazy calculation.
// pub static BLOCK_HASH_CONTRACT_ADDRESS: Lazy<ContractAddress> = ...
pub const BLOCK_HASH_CONTRACT_ADDRESS: u64 = 1;
2 changes: 2 additions & 0 deletions crates/blockifier/src/execution/deprecated_syscalls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ pub enum DeprecatedSyscallSelector {
DelegateL1Handler,
Deploy,
EmitEvent,
GetBlockHash,
GetBlockNumber,
GetBlockTimestamp,
GetCallerAddress,
Expand Down Expand Up @@ -71,6 +72,7 @@ impl TryFrom<StarkFelt> for DeprecatedSyscallSelector {
b"DelegateL1Handler" => Ok(Self::DelegateL1Handler),
b"Deploy" => Ok(Self::Deploy),
b"EmitEvent" => Ok(Self::EmitEvent),
b"GetBlockHash" => Ok(Self::GetBlockHash),
b"GetBlockNumber" => Ok(Self::GetBlockNumber),
b"GetBlockTimestamp" => Ok(Self::GetBlockTimestamp),
b"GetCallerAddress" => Ok(Self::GetCallerAddress),
Expand Down
11 changes: 7 additions & 4 deletions crates/blockifier/src/execution/syscalls/hint_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ use crate::execution::execution_utils::{
ReadOnlySegment, ReadOnlySegments,
};
use crate::execution::syscalls::{
call_contract, deploy, emit_event, get_execution_info, library_call, library_call_l1_handler,
replace_class, send_message_to_l1, storage_read, storage_write, StorageReadResponse,
StorageWriteResponse, SyscallRequest, SyscallRequestWrapper, SyscallResponse,
SyscallResponseWrapper, SyscallResult, SyscallSelector,
call_contract, deploy, emit_event, get_block_hash, get_execution_info, library_call,
library_call_l1_handler, replace_class, send_message_to_l1, storage_read, storage_write,
StorageReadResponse, StorageWriteResponse, SyscallRequest, SyscallRequestWrapper,
SyscallResponse, SyscallResponseWrapper, SyscallResult, SyscallSelector,
};
use crate::state::errors::StateError;
use crate::state::state_api::State;
Expand Down Expand Up @@ -186,6 +186,9 @@ impl<'a> SyscallHintProcessor<'a> {
SyscallSelector::EmitEvent => {
self.execute_syscall(vm, emit_event, constants::EMIT_EVENT_GAS_COST)
}
SyscallSelector::GetBlockHash => {
self.execute_syscall(vm, get_block_hash, constants::GET_BLOCK_HASH_GAS_COST)
}
SyscallSelector::GetExecutionInfo => {
self.execute_syscall(vm, get_execution_info, constants::GET_EXECUTION_INFO_GAS_COST)
}
Expand Down
47 changes: 47 additions & 0 deletions crates/blockifier/src/execution/syscalls/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use cairo_felt::Felt252;
use cairo_vm::types::relocatable::Relocatable;
use cairo_vm::vm::vm_core::VirtualMachine;
use starknet_api::block::BlockHash;
use starknet_api::core::{
calculate_contract_address, ClassHash, ContractAddress, EntryPointSelector,
};
Expand Down Expand Up @@ -283,6 +284,52 @@ pub fn emit_event(
Ok(EmitEventResponse {})
}

// GetBlockHash syscall.

#[derive(Debug, Eq, PartialEq)]

// TODO(Arni, 8/6/2023): Consider replacing `BlockNumber`.
pub struct GetBlockHashRequest {
pub block_number: StarkFelt,
}

impl SyscallRequest for GetBlockHashRequest {
fn read(vm: &VirtualMachine, ptr: &mut Relocatable) -> SyscallResult<GetBlockHashRequest> {
let block_number = stark_felt_from_ptr(vm, ptr)?;
Ok(GetBlockHashRequest { block_number })
}
}

#[derive(Debug, Eq, PartialEq)]
pub struct GetBlockHashResponse {
pub block_hash: BlockHash,
}

impl SyscallResponse for GetBlockHashResponse {
fn write(self, vm: &mut VirtualMachine, ptr: &mut Relocatable) -> WriteResponseResult {
write_stark_felt(vm, ptr, self.block_hash.0)?;
Ok(())
}
}

// Returns the block hash of a given block_number.
// Returns the expected block hash if the given block was created at least 10 blocks before the
// current block. Otherwise, returns an error.
// TODO(Arni, 11/6/2023): Implement according to the documentation above.
pub fn get_block_hash(
request: GetBlockHashRequest,
_vm: &mut VirtualMachine,
syscall_handler: &mut SyscallHintProcessor<'_>,
_remaining_gas: &mut Felt252,
) -> SyscallResult<GetBlockHashResponse> {
let key = StorageKey::try_from(request.block_number)?;
let block_hash_contract_address =
ContractAddress::try_from(StarkFelt::from(constants::BLOCK_HASH_CONTRACT_ADDRESS))?;
let block_hash =
BlockHash(syscall_handler.state.get_storage_at(block_hash_contract_address, key)?);
Ok(GetBlockHashResponse { block_hash })
}

// GetExecutionInfo syscall.

type GetExecutionInfoRequest = EmptyRequest;
Expand Down
30 changes: 30 additions & 0 deletions crates/blockifier/src/execution/syscalls/syscalls_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use starknet_api::{calldata, patricia_key, stark_felt};
use test_case::test_case;

use crate::abi::abi_utils::selector_from_name;
use crate::abi::constants;
use crate::execution::contract_class::ContractClassV0;
use crate::execution::entry_point::{
CallEntryPoint, CallExecution, CallInfo, CallType, MessageToL1, OrderedEvent,
Expand Down Expand Up @@ -122,6 +123,35 @@ fn test_emit_event() {
);
}

#[test]
fn test_get_block_hash() {
let mut state = create_test_state();

// Initialize block number -> block hash entry.
let block_number = stark_felt!(1800_u64);
let block_hash = stark_felt!(66_u64);
let key = StorageKey::try_from(block_number).unwrap();
let block_hash_contract_address =
ContractAddress::try_from(StarkFelt::from(constants::BLOCK_HASH_CONTRACT_ADDRESS)).unwrap();
state.set_storage_at(block_hash_contract_address, key, block_hash);

// Create call.
let calldata = calldata![block_number];
let entry_point_call = CallEntryPoint {
entry_point_selector: selector_from_name("test_get_block_hash"),
calldata,
..trivial_external_entry_point()
};

assert_eq!(
entry_point_call.execute_directly(&mut state).unwrap().execution,
CallExecution {
gas_consumed: stark_felt!(15750_u64),
..CallExecution::from_retdata(retdata![block_hash])
}
);
}

#[test]
fn test_get_execution_info() {
let mut state = create_test_state();
Expand Down
6 changes: 6 additions & 0 deletions crates/blockifier/src/fee/os_resources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pub static OS_RESOURCES: OsResources = {
.expect("os_resources json does not exist or cannot be deserialized.")
};

// TODO(Arni, 14/6/2023): Update `GetBlockHash` values.
fn os_resources() -> serde_json::Value {
json!({
"execute_syscalls": {
Expand Down Expand Up @@ -45,6 +46,11 @@ fn os_resources() -> serde_json::Value {
"n_memory_holes": 0,
"n_steps": 19
},
"GetBlockHash": {
"builtin_instance_counter": {},
"n_memory_holes": 0,
"n_steps": 44
},
"GetBlockNumber": {
"builtin_instance_counter": {},
"n_memory_holes": 0,
Expand Down