diff --git a/crates/blockifier/src/fee/gas_usage_test.rs b/crates/blockifier/src/fee/gas_usage_test.rs index dea634aa451..7696dc38d71 100644 --- a/crates/blockifier/src/fee/gas_usage_test.rs +++ b/crates/blockifier/src/fee/gas_usage_test.rs @@ -3,6 +3,7 @@ use std::sync::Arc; use num_rational::Ratio; use pretty_assertions::assert_eq; use rstest::{fixture, rstest}; +use starknet_api::block::StarknetVersion; use starknet_api::execution_resources::{GasAmount, GasVector}; use starknet_api::invoke_tx_args; use starknet_api::transaction::{EventContent, EventData, EventKey, GasVectorComputationMode}; @@ -29,12 +30,7 @@ use crate::test_utils::{ use crate::transaction::objects::FeeType; use crate::transaction::test_utils::account_invoke_tx; use crate::utils::u64_from_usize; -use crate::versioned_constants::{ - ResourceCost, - StarknetVersion, - VersionedConstants, - VmResourceCosts, -}; +use crate::versioned_constants::{ResourceCost, VersionedConstants, VmResourceCosts}; pub fn create_event_for_testing(keys_size: usize, data_size: usize) -> OrderedEvent { OrderedEvent { @@ -317,7 +313,8 @@ fn test_gas_computation_regression_test( // Use a constant version of the versioned constants so that version changes do not break this // test. This specific version is arbitrary. // TODO(Amos, 1/10/2024): Parameterize the version. - let mut versioned_constants = VersionedConstants::get(StarknetVersion::V0_13_2_1).clone(); + let mut versioned_constants = + VersionedConstants::get(&StarknetVersion::V0_13_2_1).unwrap().clone(); // Change the VM resource fee cost so that the L2 / L1 gas ratio is a fraction. let vm_resource_fee_cost = VmResourceCosts { diff --git a/crates/blockifier/src/versioned_constants.rs b/crates/blockifier/src/versioned_constants.rs index 4655d32c1de..57316ea6f5a 100644 --- a/crates/blockifier/src/versioned_constants.rs +++ b/crates/blockifier/src/versioned_constants.rs @@ -13,11 +13,10 @@ use semver::Version; use serde::de::Error as DeserializationError; use serde::{Deserialize, Deserializer, Serialize}; use serde_json::{Map, Number, Value}; -use starknet_api::block::GasPrice; +use starknet_api::block::{GasPrice, StarknetVersion}; use starknet_api::execution_resources::GasAmount; use starknet_api::transaction::GasVectorComputationMode; use strum::IntoEnumIterator; -use strum_macros::{EnumCount, EnumIter}; use thiserror::Error; use crate::execution::deprecated_syscalls::hint_processor::SyscallCounter; @@ -32,35 +31,7 @@ pub mod test; /// Auto-generate getters for listed versioned constants versions. macro_rules! define_versioned_constants { - ($(($variant:ident, $path_to_json:expr, $version_str:expr)),*, $latest_variant:ident) => { - /// Enum of all the Starknet versions supporting versioned constants. - #[derive(Clone, Debug, EnumCount, EnumIter, Hash, Eq, PartialEq)] - pub enum StarknetVersion { - $($variant,)* - } - - impl StarknetVersion { - pub fn path_to_versioned_constants_json(&self) -> &'static str { - match self { - $(StarknetVersion::$variant => $path_to_json,)* - } - } - - pub fn latest() -> Self { - StarknetVersion::$latest_variant - } - } - - impl From for String { - fn from(version: StarknetVersion) -> Self { - match version { - $(StarknetVersion::$variant => String::from( - stringify!($variant) - ).to_lowercase().replace("_", "."),)* - } - } - } - + ($(($variant:ident, $path_to_json:expr)),* $(,)?) => { // Static (lazy) instances of the versioned constants. // For internal use only; for access to a static instance use the `StarknetVersion` enum. paste! { @@ -75,64 +46,70 @@ macro_rules! define_versioned_constants { } /// API to access a static instance of the versioned constants. - impl From for &'static VersionedConstants { - fn from(version: StarknetVersion) -> Self { + impl TryFrom for &'static VersionedConstants { + type Error = VersionedConstantsError; + + fn try_from(version: StarknetVersion) -> VersionedConstantsResult { match version { $( StarknetVersion::$variant => { - & paste! { [] } + Ok(& paste! { [] }) } )* + _ => Err(VersionedConstantsError::InvalidStarknetVersion(version)), } } } - pub static VERSIONED_CONSTANTS_LATEST_JSON: LazyLock = LazyLock::new(|| { - let latest_variant = StarknetVersion::$latest_variant; - let path_to_json: PathBuf = [ - env!("CARGO_MANIFEST_DIR"), "src", latest_variant.path_to_versioned_constants_json() - ].iter().collect(); - fs::read_to_string(path_to_json.clone()) - .expect(&format!("Failed to read file {}.", path_to_json.display())) - }); + impl VersionedConstants { + pub fn path_to_json(version: &StarknetVersion) -> VersionedConstantsResult<&'static str> { + match version { + $(StarknetVersion::$variant => Ok($path_to_json),)* + _ => Err(VersionedConstantsError::InvalidStarknetVersion(*version)), + } + } - impl TryFrom<&str> for StarknetVersion { - type Error = VersionedConstantsError; - fn try_from(raw_version: &str) -> Result { - match raw_version { + /// Gets the constants that shipped with the current version of the Blockifier. + /// To use custom constants, initialize the struct from a file using `from_path`. + pub fn latest_constants() -> &'static Self { + Self::get(&StarknetVersion::latest()) + .expect("Latest version should support VC.") + } + + /// Gets the constants for the specified Starknet version. + pub fn get(version: &StarknetVersion) -> VersionedConstantsResult<&'static Self> { + match version { $( - $version_str => Ok(StarknetVersion::$variant), + StarknetVersion::$variant => Ok( + & paste! { [] } + ), )* - _ => Err(VersionedConstantsError::InvalidVersion { version: raw_version.to_string()}), + _ => Err(VersionedConstantsError::InvalidStarknetVersion(*version)), } } } - #[cfg(test)] - mod tests { - use crate::versioned_constants::StarknetVersion; - - #[test] - fn test_variant_name_string_consistency() { - $( - assert_eq!( - "v".to_owned() + $version_str, - String::from(StarknetVersion::$variant) - ); - )* - } - } + pub static VERSIONED_CONSTANTS_LATEST_JSON: LazyLock = LazyLock::new(|| { + let latest_variant = StarknetVersion::latest(); + let path_to_json: PathBuf = [ + env!("CARGO_MANIFEST_DIR"), + "src", + VersionedConstants::path_to_json(&latest_variant) + .expect("Latest variant should have a path to json.") + ].iter().collect(); + fs::read_to_string(path_to_json.clone()) + .expect(&format!("Failed to read file {}.", path_to_json.display())) + }); }; } define_versioned_constants! { - (V0_13_0, "../resources/versioned_constants_0_13_0.json", "0.13.0"), - (V0_13_1, "../resources/versioned_constants_0_13_1.json", "0.13.1"), - (V0_13_1_1, "../resources/versioned_constants_0_13_1_1.json", "0.13.1.1"), - (V0_13_2, "../resources/versioned_constants_0_13_2.json", "0.13.2"), - (V0_13_2_1, "../resources/versioned_constants_0_13_2_1.json", "0.13.2.1"), - (V0_13_3, "../resources/versioned_constants_0_13_3.json", "0.13.3"), - V0_13_3 + (V0_13_0, "../resources/versioned_constants_0_13_0.json"), + (V0_13_1, "../resources/versioned_constants_0_13_1.json"), + (V0_13_1_1, "../resources/versioned_constants_0_13_1_1.json"), + (V0_13_2, "../resources/versioned_constants_0_13_2.json"), + (V0_13_2_1, "../resources/versioned_constants_0_13_2_1.json"), + (V0_13_3, "../resources/versioned_constants_0_13_3.json"), } pub type ResourceCost = Ratio; @@ -213,18 +190,7 @@ pub struct VersionedConstants { } impl VersionedConstants { - /// Gets the constants that shipped with the current version of the Blockifier. - /// To use custom constants, initialize the struct from a file using `from_path`. - pub fn latest_constants() -> &'static Self { - Self::get(StarknetVersion::latest()) - } - - /// Gets the constants for the specified Starknet version. - pub fn get(version: StarknetVersion) -> &'static Self { - version.into() - } - - pub fn from_path(path: &Path) -> Result { + pub fn from_path(path: &Path) -> VersionedConstantsResult { Ok(serde_json::from_reader(std::fs::File::open(path)?)?) } @@ -768,8 +734,12 @@ pub enum VersionedConstantsError { ParseError(#[from] serde_json::Error), #[error("Invalid version: {version:?}")] InvalidVersion { version: String }, + #[error("Invalid Starknet version: {0}")] + InvalidStarknetVersion(StarknetVersion), } +pub type VersionedConstantsResult = Result; + #[derive(Debug, Error)] pub enum OsConstantsSerdeError { #[error("Value cannot be cast into u64: {0}")] @@ -807,7 +777,7 @@ struct ResourceParamsRaw { impl TryFrom for ResourcesParams { type Error = VersionedConstantsError; - fn try_from(mut json_data: ResourceParamsRaw) -> Result { + fn try_from(mut json_data: ResourceParamsRaw) -> VersionedConstantsResult { let constant_value = json_data.raw_resource_params_as_dict.remove("constant"); let calldata_factor_value = json_data.raw_resource_params_as_dict.remove("calldata_factor"); diff --git a/crates/blockifier/src/versioned_constants_test.rs b/crates/blockifier/src/versioned_constants_test.rs index 32ebe68d76e..000c5e56650 100644 --- a/crates/blockifier/src/versioned_constants_test.rs +++ b/crates/blockifier/src/versioned_constants_test.rs @@ -146,3 +146,8 @@ fn test_old_json_parsing() { fn test_all_jsons_in_enum() { assert_eq!(StarknetVersion::iter().count(), all_jsons_in_dir().count()); } + +#[test] +fn test_latest_no_panic() { + VersionedConstants::latest_constants(); +} diff --git a/crates/blockifier_reexecution/src/state_reader/rpc_https_test.rs b/crates/blockifier_reexecution/src/state_reader/rpc_https_test.rs index b0144724d7f..d056a98e34e 100644 --- a/crates/blockifier_reexecution/src/state_reader/rpc_https_test.rs +++ b/crates/blockifier_reexecution/src/state_reader/rpc_https_test.rs @@ -1,6 +1,5 @@ use assert_matches::assert_matches; use blockifier::blockifier::block::BlockInfo; -use blockifier::versioned_constants::StarknetVersion; use pretty_assertions::assert_eq; use rstest::{fixture, rstest}; use starknet_api::block::BlockNumber; diff --git a/crates/blockifier_reexecution/src/state_reader/test_state_reader.rs b/crates/blockifier_reexecution/src/state_reader/test_state_reader.rs index 66d5129de66..5fa5f480cb1 100644 --- a/crates/blockifier_reexecution/src/state_reader/test_state_reader.rs +++ b/crates/blockifier_reexecution/src/state_reader/test_state_reader.rs @@ -7,9 +7,9 @@ use blockifier::execution::contract_class::ContractClass as BlockifierContractCl use blockifier::state::cached_state::CachedState; use blockifier::state::errors::StateError; use blockifier::state::state_api::{StateReader, StateResult}; -use blockifier::versioned_constants::{StarknetVersion, VersionedConstants}; +use blockifier::versioned_constants::VersionedConstants; use serde_json::{json, to_value}; -use starknet_api::block::BlockNumber; +use starknet_api::block::{BlockNumber, StarknetVersion}; use starknet_api::core::{ClassHash, CompiledClassHash, ContractAddress, Nonce}; use starknet_api::state::StorageKey; use starknet_api::transaction::{Transaction, TransactionHash}; @@ -156,8 +156,8 @@ impl TestStateReader { .collect::>() } - pub fn get_versioned_constants(&self) -> StateResult<&'static VersionedConstants> { - Ok(self.get_starknet_version()?.into()) + pub fn get_versioned_constants(&self) -> ReexecutionResult<&'static VersionedConstants> { + Ok(VersionedConstants::get(&self.get_starknet_version()?)?) } pub fn get_block_context(&self) -> StateResult { diff --git a/crates/native_blockifier/src/lib.rs b/crates/native_blockifier/src/lib.rs index 082826e7459..c4a43e66856 100644 --- a/crates/native_blockifier/src/lib.rs +++ b/crates/native_blockifier/src/lib.rs @@ -20,12 +20,12 @@ pub mod state_readers; pub mod storage; pub mod test_utils; -use blockifier::versioned_constants::StarknetVersion; use errors::{add_py_exceptions, UndeclaredClassHashError}; use py_block_executor::PyBlockExecutor; use py_objects::PyExecutionResources; use py_validator::PyValidator; use pyo3::prelude::*; +use starknet_api::block::StarknetVersion; use storage::StorageConfig; use crate::py_objects::PyVersionedConstantsOverrides; diff --git a/crates/papyrus_execution/src/lib.rs b/crates/papyrus_execution/src/lib.rs index cfb61b6fd20..bd67d187ca5 100644 --- a/crates/papyrus_execution/src/lib.rs +++ b/crates/papyrus_execution/src/lib.rs @@ -42,10 +42,7 @@ use blockifier::transaction::objects::{ }; use blockifier::transaction::transaction_execution::Transaction as BlockifierTransaction; use blockifier::transaction::transactions::ExecutableTransaction; -use blockifier::versioned_constants::{ - StarknetVersion as BlockifierStarknetVersion, - VersionedConstants, -}; +use blockifier::versioned_constants::VersionedConstants; use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; use cairo_vm::types::builtin_name::BuiltinName; use cairo_vm::vm::runners::cairo_runner::ExecutionResources; @@ -864,15 +861,17 @@ fn get_versioned_constants( Some(starknet_version) => { let version = starknet_version.to_string(); let blockifier_starknet_version = if version == STARKNET_VERSION_O_13_0 { - BlockifierStarknetVersion::V0_13_0 + StarknetVersion::V0_13_0 } else if version == STARKNET_VERSION_O_13_1 { - BlockifierStarknetVersion::V0_13_1 + StarknetVersion::V0_13_1 } else if version == STARKNET_VERSION_O_13_2 { - BlockifierStarknetVersion::V0_13_2 + StarknetVersion::V0_13_2 } else { - BlockifierStarknetVersion::V0_13_3 + StarknetVersion::V0_13_3 }; - VersionedConstants::get(blockifier_starknet_version) + VersionedConstants::get(&blockifier_starknet_version).unwrap_or_else(|_| { + panic!("No versioned constants for version: {version}"); + }) } None => VersionedConstants::latest_constants(), }; diff --git a/crates/starknet_api/src/block.rs b/crates/starknet_api/src/block.rs index 3705c6629fb..05234c717b6 100644 --- a/crates/starknet_api/src/block.rs +++ b/crates/starknet_api/src/block.rs @@ -62,6 +62,12 @@ pub enum StarknetVersion { V0_13_3, } +impl StarknetVersion { + pub fn latest() -> Self { + Self::V0_13_3 + } +} + impl From<&StarknetVersion> for Vec { fn from(value: &StarknetVersion) -> Self { match value { @@ -131,6 +137,12 @@ impl Display for StarknetVersion { } } +impl From for String { + fn from(version: StarknetVersion) -> Self { + format!("{version}") + } +} + impl TryFrom for StarknetVersion { type Error = StarknetApiError; @@ -142,6 +154,13 @@ impl TryFrom for StarknetVersion { } } +impl TryFrom<&str> for StarknetVersion { + type Error = StarknetApiError; + fn try_from(starknet_version: &str) -> Result { + Self::try_from(starknet_version.to_string()) + } +} + impl Serialize for StarknetVersion { fn serialize( &self, diff --git a/crates/starknet_api/src/block_test.rs b/crates/starknet_api/src/block_test.rs index 13b04f8ceb7..29e2f87e637 100644 --- a/crates/starknet_api/src/block_test.rs +++ b/crates/starknet_api/src/block_test.rs @@ -69,3 +69,12 @@ fn test_version_order() { } } } + +#[test] +fn test_latest_version() { + let latest = StarknetVersion::latest(); + assert_eq!(StarknetVersion::default(), latest); + for version in StarknetVersion::iter() { + assert!(version <= latest); + } +}