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

Commit

Permalink
Add skeleton for the get_block_hash syscall.
Browse files Browse the repository at this point in the history
  • Loading branch information
ArniStarkware committed Jun 12, 2023
1 parent 2704651 commit fd76200
Show file tree
Hide file tree
Showing 9 changed files with 2,351 additions and 1,665 deletions.

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 @@ -33,10 +33,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 @@ -185,6 +185,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
50 changes: 50 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,55 @@ 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 most 1024 blocks before the
// latest block and at least 10 blocks before. Otherwise, returns a default value or an error
// respectively.
// 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))?;
Ok(GetBlockHashResponse {
block_hash: BlockHash(
syscall_handler.state.get_storage_at(block_hash_contract_address, key)?,
),
})
}

// GetExecutionInfo syscall.

type GetExecutionInfoRequest = EmptyRequest;
Expand Down
32 changes: 32 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,37 @@ fn test_emit_event() {
);
}

// TODO(Arni, 11/6/2023): Initialize the "contract" at BLOCK_HASH_CONTRACT_ADDRESS.
#[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!(0x42_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()
};

// Run entry point and test result.
assert_eq!(
entry_point_call.execute_directly(&mut state).unwrap().execution,
CallExecution {
gas_consumed: stark_felt!(0x3d86_u128),
..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

0 comments on commit fd76200

Please sign in to comment.