Skip to content

Commit

Permalink
refactor: move VersionedConstants macro, errors from Blockifier to St…
Browse files Browse the repository at this point in the history
…arknetAPI
  • Loading branch information
ayeletstarkware committed Jan 9, 2025
1 parent 6f72e5c commit 55013d2
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 97 deletions.
4 changes: 4 additions & 0 deletions crates/blockifier/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,7 @@ required-features = ["testing"]
name = "feature_contracts_compatibility_test"
path = "tests/feature_contracts_compatibility_test.rs"
required-features = ["testing"]

[package.metadata.cargo-machete]
# `paste` is used in the `define_versioned_constants!` macro but may be falsely detected as unused.
ignored = ["paste"]
102 changes: 7 additions & 95 deletions crates/blockifier/src/versioned_constants.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::collections::{BTreeMap, HashMap, HashSet};
use std::path::{Path, PathBuf};
use std::sync::{Arc, LazyLock};
use std::{fs, io};
use std::path::Path;
use std::sync::Arc;

use cairo_vm::types::builtin_name::BuiltinName;
use cairo_vm::vm::runners::cairo_runner::ExecutionResources;
Expand All @@ -10,14 +9,14 @@ use num_rational::Ratio;
use num_traits::Inv;
use papyrus_config::dumping::{ser_param, SerializeConfig};
use papyrus_config::{ParamPath, ParamPrivacyInput, SerializedParam};
use paste::paste;
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, StarknetVersion};
use starknet_api::block::GasPrice;
use starknet_api::contract_class::SierraVersion;
use starknet_api::core::ContractAddress;
use starknet_api::define_versioned_constants;
use starknet_api::execution_resources::{GasAmount, GasVector};
use starknet_api::transaction::fields::GasVectorComputationMode;
use starknet_infra_utils::compile_time_cargo_manifest_dir;
Expand All @@ -36,89 +35,16 @@ use crate::utils::u64_from_usize;
#[path = "versioned_constants_test.rs"]
pub mod test;

/// Auto-generate getters for listed versioned constants versions.
macro_rules! define_versioned_constants {
($(($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! {
$(
pub(crate) const [<VERSIONED_CONSTANTS_ $variant:upper _JSON>]: &str =
include_str!($path_to_json);
pub static [<VERSIONED_CONSTANTS_ $variant:upper>]: LazyLock<VersionedConstants> = LazyLock::new(|| {
serde_json::from_str([<VERSIONED_CONSTANTS_ $variant:upper _JSON>])
.expect(&format!("Versioned constants {} is malformed.", $path_to_json))
});
)*
}

/// API to access a static instance of the versioned constants.
impl TryFrom<StarknetVersion> for &'static VersionedConstants {
type Error = VersionedConstantsError;

fn try_from(version: StarknetVersion) -> VersionedConstantsResult<Self> {
match version {
$(
StarknetVersion::$variant => {
Ok(& paste! { [<VERSIONED_CONSTANTS_ $variant:upper>] })
}
)*
_ => Err(VersionedConstantsError::InvalidStarknetVersion(version)),
}
}
}

impl VersionedConstants {
pub fn path_to_json(version: &StarknetVersion) -> VersionedConstantsResult<&'static str> {
match version {
$(StarknetVersion::$variant => Ok($path_to_json),)*
_ => Err(VersionedConstantsError::InvalidStarknetVersion(*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 {
$(
StarknetVersion::$variant => Ok(
& paste! { [<VERSIONED_CONSTANTS_ $variant:upper>] }
),
)*
_ => Err(VersionedConstantsError::InvalidStarknetVersion(*version)),
}
}
}

pub static VERSIONED_CONSTANTS_LATEST_JSON: LazyLock<String> = LazyLock::new(|| {
let latest_variant = StarknetVersion::LATEST;
let path_to_json: PathBuf = [
compile_time_cargo_manifest_dir!(),
"src".into(),
VersionedConstants::path_to_json(&latest_variant)
.expect("Latest variant should have a path to json.").into()
].iter().collect();
fs::read_to_string(path_to_json.clone())
.expect(&format!("Failed to read file {}.", path_to_json.display()))
});
};
}

define_versioned_constants! {
define_versioned_constants!(
VersionedConstants,
(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"),
(V0_13_4, "../resources/versioned_constants_0_13_4.json"),
}
);

pub type ResourceCost = Ratio<u64>;

Expand Down Expand Up @@ -1160,20 +1086,6 @@ impl OsConstantsRawJson {
}
}

#[derive(Debug, Error)]
pub enum VersionedConstantsError {
#[error(transparent)]
IoError(#[from] io::Error),
#[error("JSON file cannot be serialized into VersionedConstants: {0}")]
ParseError(#[from] serde_json::Error),
#[error("Invalid version: {version:?}")]
InvalidVersion { version: String },
#[error("Invalid Starknet version: {0}")]
InvalidStarknetVersion(StarknetVersion),
}

pub type VersionedConstantsResult<T> = Result<T, VersionedConstantsError>;

#[derive(Debug, Error)]
pub enum OsConstantsSerdeError {
#[error("Value cannot be cast into u64: {0}")]
Expand Down
2 changes: 1 addition & 1 deletion crates/blockifier_reexecution/src/state_reader/errors.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use blockifier::state::errors::StateError;
use blockifier::transaction::errors::TransactionExecutionError;
use blockifier::versioned_constants::VersionedConstantsError;
use serde_json::Error as SerdeError;
use starknet_api::versioned_constants_logic::VersionedConstantsError;
use starknet_api::StarknetApiError;
use starknet_gateway::errors::RPCStateReaderError;
use thiserror::Error;
Expand Down
3 changes: 2 additions & 1 deletion crates/papyrus_execution/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ use blockifier::transaction::objects::{
};
use blockifier::transaction::transaction_execution::Transaction as BlockifierTransaction;
use blockifier::transaction::transactions::ExecutableTransaction;
use blockifier::versioned_constants::{VersionedConstants, VersionedConstantsError};
use blockifier::versioned_constants::VersionedConstants;
use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass;
use cairo_vm::types::builtin_name::BuiltinName;
use execution_utils::{get_trace_constructor, induced_state_diff};
Expand Down Expand Up @@ -80,6 +80,7 @@ use starknet_api::transaction::{
TransactionVersion,
};
use starknet_api::transaction_hash::get_transaction_hash;
use starknet_api::versioned_constants_logic::VersionedConstantsError;
use starknet_api::StarknetApiError;
use starknet_types_core::felt::Felt;
use state_reader::ExecutionStateReader;
Expand Down
1 change: 1 addition & 0 deletions crates/starknet_api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub mod test_utils;
pub mod transaction;
pub mod transaction_hash;
pub mod type_utils;
pub mod versioned_constants_logic;

use std::num::ParseIntError;

Expand Down
107 changes: 107 additions & 0 deletions crates/starknet_api/src/versioned_constants_logic.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
use std::io;

use thiserror::Error;

use crate::block::StarknetVersion;

#[derive(Debug, Error)]
pub enum VersionedConstantsError {
#[error(transparent)]
IoError(#[from] io::Error),
#[error("JSON file cannot be serialized into VersionedConstants: {0}")]
ParseError(#[from] serde_json::Error),
#[error("Invalid version: {version:?}")]
InvalidVersion { version: String },
#[error("Invalid Starknet version: {0}")]
InvalidStarknetVersion(StarknetVersion),
}

pub type VersionedConstantsResult<T> = Result<T, VersionedConstantsError>;

/// Auto-generate getters for listed versioned constants versions.
#[macro_export]
macro_rules! define_versioned_constants {
($struct_name:ident, $(($variant:ident, $path_to_json:expr)),* $(,)?) => {
use infra_utils::compile_time_cargo_manifest_dir;
use paste::paste;
use std::fs;
use std::path::PathBuf;
use std::sync::LazyLock;
use starknet_api::block::StarknetVersion;
use starknet_api::versioned_constants_logic::{
VersionedConstantsError, VersionedConstantsResult,
};
// Static (lazy) instances of the versioned constants.
// For internal use only; for access to a static instance use the `StarknetVersion` enum.
paste! {
$(
pub(crate) const [<VERSIONED_CONSTANTS_ $variant:upper _JSON>]: &str =
include_str!($path_to_json);
/// Static instance of the versioned constants for the Starknet version.
pub static [<VERSIONED_CONSTANTS_ $variant:upper>]: LazyLock<VersionedConstants> =
LazyLock::new(|| {
serde_json::from_str([<VERSIONED_CONSTANTS_ $variant:upper _JSON>])
.expect(&format!("Versioned constants {} is malformed.", $path_to_json))
});
)*
}

/// API to access a static instance of the versioned constants.
impl TryFrom<StarknetVersion> for &'static $struct_name {
type Error = VersionedConstantsError;

fn try_from(version: StarknetVersion) -> VersionedConstantsResult<Self> {
match version {
$(
StarknetVersion::$variant => {
Ok(& paste! { [<VERSIONED_CONSTANTS_ $variant:upper>] })
}
)*
_ => Err(VersionedConstantsError::InvalidStarknetVersion(version)),
}
}
}

impl $struct_name {
/// Gets the path to the JSON file for the specified Starknet version.
pub fn path_to_json(version: &StarknetVersion) -> VersionedConstantsResult<&'static str> {
match version {
$(StarknetVersion::$variant => Ok($path_to_json),)*
_ => Err(VersionedConstantsError::InvalidStarknetVersion(*version)),
}
}

/// Gets the constants that shipped with the current version of the Starknet.
/// 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 {
$(
StarknetVersion::$variant => Ok(
& paste! { [<VERSIONED_CONSTANTS_ $variant:upper>] }
),
)*
_ => Err(VersionedConstantsError::InvalidStarknetVersion(*version)),
}
}
}

/// Gets a string of the constants of the latest version of Starknet.
pub static VERSIONED_CONSTANTS_LATEST_JSON: LazyLock<String> = LazyLock::new(|| {
let latest_variant = StarknetVersion::LATEST;
let path_to_json: PathBuf = [
compile_time_cargo_manifest_dir!(),
"src".into(),
VersionedConstants::path_to_json(&latest_variant)
.expect("Latest variant should have a path to json.").into()
].iter().collect();
fs::read_to_string(path_to_json.clone())
.expect(&format!("Failed to read file {}.", path_to_json.display()))
});
};
}

0 comments on commit 55013d2

Please sign in to comment.