Skip to content

Commit

Permalink
feat(blockifier): add OS constants (starkware-libs#2281)
Browse files Browse the repository at this point in the history
  • Loading branch information
nimrod-starkware authored Dec 2, 2024
1 parent 88b91d5 commit 111c6fd
Show file tree
Hide file tree
Showing 16 changed files with 101 additions and 30 deletions.
6 changes: 5 additions & 1 deletion crates/blockifier/resources/versioned_constants_0_13_0.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@
"validate_deploy_entry_point_selector": "0x36fcbf06cd96843058359e1a75928beacfac10727dab22a3972f0af8aa92895",
"transfer_entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e",
"default_entry_point_selector": 0,
"block_hash_contract_address": 1,
"stored_block_hash_buffer": 10,
"step_gas_cost": 100,
"range_check_gas_cost": 70,
Expand All @@ -80,6 +79,11 @@
"add_mod_gas_cost": 0,
"mul_mod_gas_cost": 0,
"memory_hole_gas_cost": 10,
"os_contract_addresses": {
"block_hash_contract_address": 1,
"alias_contract_address": 2,
"reserved_contract_address": 3
},
"default_initial_gas_cost": {
"step_gas_cost": 100000000
},
Expand Down
6 changes: 5 additions & 1 deletion crates/blockifier/resources/versioned_constants_0_13_1.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@
"validate_deploy_entry_point_selector": "0x36fcbf06cd96843058359e1a75928beacfac10727dab22a3972f0af8aa92895",
"transfer_entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e",
"default_entry_point_selector": 0,
"block_hash_contract_address": 1,
"stored_block_hash_buffer": 10,
"step_gas_cost": 100,
"range_check_gas_cost": 70,
Expand All @@ -79,6 +78,11 @@
"poseidon_gas_cost": 0,
"add_mod_gas_cost": 0,
"mul_mod_gas_cost": 0,
"os_contract_addresses": {
"block_hash_contract_address": 1,
"alias_contract_address": 2,
"reserved_contract_address": 3
},
"memory_hole_gas_cost": 10,
"default_initial_gas_cost": {
"step_gas_cost": 100000000
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@
"validate_deploy_entry_point_selector": "0x36fcbf06cd96843058359e1a75928beacfac10727dab22a3972f0af8aa92895",
"transfer_entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e",
"default_entry_point_selector": 0,
"block_hash_contract_address": 1,
"stored_block_hash_buffer": 10,
"step_gas_cost": 100,
"range_check_gas_cost": 70,
Expand All @@ -80,6 +79,11 @@
"add_mod_gas_cost": 0,
"mul_mod_gas_cost": 0,
"memory_hole_gas_cost": 10,
"os_contract_addresses": {
"block_hash_contract_address": 1,
"alias_contract_address": 2,
"reserved_contract_address": 3
},
"default_initial_gas_cost": {
"step_gas_cost": 100000000
},
Expand Down
6 changes: 5 additions & 1 deletion crates/blockifier/resources/versioned_constants_0_13_2.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@
"max_recursion_depth": 50,
"segment_arena_cells": false,
"os_constants": {
"block_hash_contract_address": 1,
"call_contract_gas_cost": {
"entry_point_gas_cost": 1,
"step_gas_cost": 10,
Expand Down Expand Up @@ -125,6 +124,11 @@
},
"memory_hole_gas_cost": 10,
"nop_entry_point_offset": -1,
"os_contract_addresses": {
"block_hash_contract_address": 1,
"alias_contract_address": 2,
"reserved_contract_address": 3
},
"range_check_gas_cost": 70,
"pedersen_gas_cost": 0,
"bitwise_builtin_gas_cost": 594,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@
"enable_reverts": false,
"segment_arena_cells": false,
"os_constants": {
"block_hash_contract_address": 1,
"call_contract_gas_cost": {
"entry_point_gas_cost": 1,
"step_gas_cost": 10,
Expand Down Expand Up @@ -125,6 +124,11 @@
},
"memory_hole_gas_cost": 10,
"nop_entry_point_offset": -1,
"os_contract_addresses": {
"block_hash_contract_address": 1,
"alias_contract_address": 2,
"reserved_contract_address": 3
},
"range_check_gas_cost": 70,
"pedersen_gas_cost": 0,
"bitwise_builtin_gas_cost": 594,
Expand Down
6 changes: 5 additions & 1 deletion crates/blockifier/resources/versioned_constants_0_13_3.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@
"enable_reverts": false,
"segment_arena_cells": false,
"os_constants": {
"block_hash_contract_address": 1,
"call_contract_gas_cost": {
"entry_point_gas_cost": 1,
"step_gas_cost": 10,
Expand Down Expand Up @@ -125,6 +124,11 @@
},
"memory_hole_gas_cost": 10,
"nop_entry_point_offset": -1,
"os_contract_addresses": {
"block_hash_contract_address": 1,
"alias_contract_address": 2,
"reserved_contract_address": 3
},
"range_check_gas_cost": 70,
"pedersen_gas_cost": 0,
"bitwise_builtin_gas_cost": 594,
Expand Down
6 changes: 5 additions & 1 deletion crates/blockifier/resources/versioned_constants_0_13_4.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@
"max_recursion_depth": 50,
"segment_arena_cells": false,
"os_constants": {
"block_hash_contract_address": 1,
"call_contract_gas_cost": {
"entry_point_gas_cost": 1,
"step_gas_cost": 860,
Expand Down Expand Up @@ -126,6 +125,11 @@
},
"memory_hole_gas_cost": 10,
"nop_entry_point_offset": -1,
"os_contract_addresses": {
"block_hash_contract_address": 1,
"alias_contract_address": 2,
"reserved_contract_address": 3
},
"range_check_gas_cost": 70,
"pedersen_gas_cost": 4050,
"bitwise_builtin_gas_cost": 583,
Expand Down
7 changes: 0 additions & 7 deletions crates/blockifier/src/abi/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,5 @@ pub const N_MEMORY_HOLES: &str = "n_memory_holes";
pub const CAIRO0_ENTRY_POINT_STRUCT_SIZE: usize = 2;
pub const N_STEPS_PER_PEDERSEN: usize = 8;

// 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;

// The block number -> block hash mapping is written for the current block number minus this number.
pub const STORED_BLOCK_HASH_BUFFER: u64 = 10;
6 changes: 3 additions & 3 deletions crates/blockifier/src/blockifier/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,12 @@ use starknet_api::block::{
GasPrices,
NonzeroGasPrice,
};
use starknet_api::core::ContractAddress;
use starknet_api::state::StorageKey;

use crate::abi::constants;
use crate::state::errors::StateError;
use crate::state::state_api::{State, StateResult};
use crate::versioned_constants::VersionedConstants;
use crate::versioned_constants::{OsConstants, VersionedConstants};

#[cfg(test)]
#[path = "block_test.rs"]
Expand Down Expand Up @@ -78,12 +77,13 @@ pub fn pre_process_block(
state: &mut dyn State,
old_block_number_and_hash: Option<BlockHashAndNumber>,
next_block_number: BlockNumber,
os_constants: &OsConstants,
) -> StateResult<()> {
let should_block_hash_be_provided =
next_block_number >= BlockNumber(constants::STORED_BLOCK_HASH_BUFFER);
if let Some(BlockHashAndNumber { number, hash }) = old_block_number_and_hash {
let block_hash_contract_address =
ContractAddress::from(constants::BLOCK_HASH_CONTRACT_ADDRESS);
os_constants.os_contract_addresses.block_hash_contract_address();
let block_number_as_storage_key = StorageKey::from(number.0);
state.set_storage_at(block_hash_contract_address, block_number_as_storage_key, hash.0)?;
} else if should_block_hash_be_provided {
Expand Down
10 changes: 6 additions & 4 deletions crates/blockifier/src/blockifier/block_test.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use starknet_api::block::{BlockHash, BlockHashAndNumber, BlockNumber};
use starknet_api::core::ContractAddress;
use starknet_api::felt;
use starknet_api::state::StorageKey;

Expand All @@ -10,11 +9,13 @@ use crate::state::state_api::StateReader;
use crate::test_utils::contracts::FeatureContract;
use crate::test_utils::initial_test_state::test_state;
use crate::test_utils::{CairoVersion, BALANCE};
use crate::versioned_constants::VersionedConstants;

#[test]
fn test_pre_process_block() {
let test_contract = FeatureContract::TestContract(CairoVersion::Cairo1);
let mut state = test_state(&ChainInfo::create_for_testing(), BALANCE, &[(test_contract, 1)]);
let os_constants = VersionedConstants::create_for_testing().os_constants;

// Test the positive flow of pre_process_block inside the allowed block number interval
let block_number = BlockNumber(constants::STORED_BLOCK_HASH_BUFFER);
Expand All @@ -23,22 +24,23 @@ fn test_pre_process_block() {
&mut state,
Some(BlockHashAndNumber { hash: BlockHash(block_hash), number: block_number }),
block_number,
&os_constants,
)
.unwrap();

let written_hash = state.get_storage_at(
ContractAddress::from(constants::BLOCK_HASH_CONTRACT_ADDRESS),
os_constants.os_contract_addresses.block_hash_contract_address(),
StorageKey::from(block_number.0),
);
assert_eq!(written_hash.unwrap(), block_hash);

// Test that block pre-process with block hash None is successful only within the allowed
// block number interval.
let block_number = BlockNumber(constants::STORED_BLOCK_HASH_BUFFER - 1);
assert!(pre_process_block(&mut state, None, block_number).is_ok());
assert!(pre_process_block(&mut state, None, block_number, &os_constants).is_ok());

let block_number = BlockNumber(constants::STORED_BLOCK_HASH_BUFFER);
let error = pre_process_block(&mut state, None, block_number);
let error = pre_process_block(&mut state, None, block_number, &os_constants);
assert_eq!(
format!(
"A block hash must be provided for block number > {}.",
Expand Down
1 change: 1 addition & 0 deletions crates/blockifier/src/blockifier/transaction_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ impl<S: StateReader> TransactionExecutor<S> {
&mut block_state,
old_block_number_and_hash,
block_context.block_info().block_number,
&block_context.versioned_constants.os_constants,
)?;
Ok(Self::new(block_state, block_context, config))
}
Expand Down
10 changes: 8 additions & 2 deletions crates/blockifier/src/execution/syscalls/syscall_base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,14 @@ impl<'state> SyscallHandlerBase<'state> {
}

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_contract_address = self
.context
.tx_context
.block_context
.versioned_constants
.os_constants
.os_contract_addresses
.block_hash_contract_address();
Ok(self.state.get_storage_at(block_hash_contract_address, key)?)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use pretty_assertions::assert_eq;
use starknet_api::abi::abi_utils::selector_from_name;
use starknet_api::core::ContractAddress;
use starknet_api::execution_utils::format_panic_data;
use starknet_api::state::StorageKey;
use starknet_api::{calldata, felt};
Expand All @@ -22,6 +21,7 @@ use crate::test_utils::{
BALANCE,
CURRENT_BLOCK_NUMBER,
};
use crate::versioned_constants::VersionedConstants;
use crate::{check_entry_point_execution_error_for_custom_hint, retdata};

fn initialize_state(test_contract: FeatureContract) -> (CachedState<DictStateReader>, Felt, Felt) {
Expand All @@ -33,8 +33,10 @@ fn initialize_state(test_contract: FeatureContract) -> (CachedState<DictStateRea
let block_number = felt!(upper_bound_block_number);
let block_hash = felt!(66_u64);
let key = StorageKey::try_from(block_number).unwrap();
let block_hash_contract_address =
ContractAddress::try_from(Felt::from(constants::BLOCK_HASH_CONTRACT_ADDRESS)).unwrap();
let block_hash_contract_address = VersionedConstants::create_for_testing()
.os_constants
.os_contract_addresses
.block_hash_contract_address();
state.set_storage_at(block_hash_contract_address, key, block_hash).unwrap();

(state, block_number, block_hash)
Expand Down
36 changes: 33 additions & 3 deletions crates/blockifier/src/versioned_constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use serde::de::Error as DeserializationError;
use serde::{Deserialize, Deserializer, Serialize};
use serde_json::{Map, Number, Value};
use starknet_api::block::{GasPrice, StarknetVersion};
use starknet_api::core::ContractAddress;
use starknet_api::execution_resources::{GasAmount, GasVector};
use starknet_api::transaction::fields::GasVectorComputationMode;
use strum::IntoEnumIterator;
Expand Down Expand Up @@ -691,15 +692,15 @@ impl GasCosts {
pub struct OsConstants {
pub gas_costs: GasCosts,
pub validate_rounding_consts: ValidateRoundingConsts,
pub os_contract_addresses: OsContractAddresses,
}

impl OsConstants {
// List of additinal os constants, beside the gas cost and validate rounding constants, that are
// not used by the blockifier but included for transparency. These constanst will be ignored
// during the creation of the struct containing the gas costs.

const ADDITIONAL_FIELDS: [&'static str; 29] = [
"block_hash_contract_address",
const ADDITIONAL_FIELDS: [&'static str; 28] = [
"constructor_entry_point_selector",
"default_entry_point_selector",
"entry_point_type_constructor",
Expand Down Expand Up @@ -747,10 +748,38 @@ impl TryFrom<OsConstantsRawJson> for OsConstants {
fn try_from(raw_json_data: OsConstantsRawJson) -> Result<Self, Self::Error> {
let gas_costs = GasCosts::try_from(&raw_json_data)?;
let validate_rounding_consts = raw_json_data.validate_rounding_consts;
let os_constants = OsConstants { gas_costs, validate_rounding_consts };
let os_contract_addresses = raw_json_data.os_contract_addresses;
let os_constants =
OsConstants { gas_costs, validate_rounding_consts, os_contract_addresses };
Ok(os_constants)
}
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct OsContractAddresses {
block_hash_contract_address: u8,
alias_contract_address: u8,
reserved_contract_address: u8,
}

impl OsContractAddresses {
pub fn block_hash_contract_address(&self) -> ContractAddress {
ContractAddress::from(self.block_hash_contract_address)
}

pub fn alias_contract_address(&self) -> ContractAddress {
ContractAddress::from(self.alias_contract_address)
}

pub fn reserved_contract_address(&self) -> ContractAddress {
ContractAddress::from(self.reserved_contract_address)
}
}

impl Default for OsContractAddresses {
fn default() -> Self {
VersionedConstants::latest_constants().os_constants.os_contract_addresses
}
}

// Intermediate representation of the JSON file in order to make the deserialization easier, using a
// regular try_from.
Expand All @@ -760,6 +789,7 @@ struct OsConstantsRawJson {
raw_json_file_as_dict: IndexMap<String, Value>,
#[serde(default)]
validate_rounding_consts: ValidateRoundingConsts,
os_contract_addresses: OsContractAddresses,
}

impl OsConstantsRawJson {
Expand Down
4 changes: 4 additions & 0 deletions crates/blockifier/src/versioned_constants_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ fn check_constants_serde_error(json_data: &str, expected_error_message: &str) {
let mut json_data_raw: IndexMap<String, Value> = serde_json::from_str(json_data).unwrap();
json_data_raw.insert("validate_block_number_rounding".to_string(), 0.into());
json_data_raw.insert("validate_timestamp_rounding".to_string(), 0.into());
json_data_raw.insert(
"os_contract_addresses".to_string(),
serde_json::to_value(OsContractAddresses::default()).unwrap(),
);

let json_data = &serde_json::to_string(&json_data_raw).unwrap();

Expand Down
7 changes: 6 additions & 1 deletion crates/papyrus_execution/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,12 @@ fn create_block_context(
);
let next_block_number = block_context.block_info().block_number;

pre_process_block(cached_state, ten_blocks_ago, next_block_number)?;
pre_process_block(
cached_state,
ten_blocks_ago,
next_block_number,
&versioned_constants.os_constants,
)?;
Ok(block_context)
}

Expand Down

0 comments on commit 111c6fd

Please sign in to comment.