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

Commit

Permalink
feat: expose versioned constants from past versions (#2049)
Browse files Browse the repository at this point in the history
Signed-off-by: Dori Medini <[email protected]>
  • Loading branch information
dorimedini-starkware authored Jul 19, 2024
1 parent 3afe8b2 commit 08da831
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 20 deletions.
5 changes: 3 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ num-rational = { version = "0.4", features = ["serde"] }
num-traits = "0.2"
once_cell = "1.19.0"
papyrus_storage = "0.4.0-dev.4"
paste = "1.0.15"
phf = { version = "0.11", features = ["macros"] }
pretty_assertions = "1.2.1"
pyo3 = "0.19.1"
Expand Down
1 change: 1 addition & 0 deletions crates/blockifier/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ num-integer.workspace = true
num-rational.workspace = true
num-traits.workspace = true
once_cell.workspace = true
paste.workspace = true
phf.workspace = true
rand = { workspace = true, optional = true }
rstest = { workspace = true, optional = true }
Expand Down
13 changes: 7 additions & 6 deletions crates/blockifier/src/test_utils/struct_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use crate::transaction::objects::{
DeprecatedTransactionInfo, FeeType, TransactionFeeResult, TransactionInfo, TransactionResources,
};
use crate::versioned_constants::{
GasCosts, OsConstants, VersionedConstants, DEFAULT_CONSTANTS_JSON,
GasCosts, OsConstants, VersionedConstants, VERSIONED_CONSTANTS_LATEST_JSON,
};

impl CallEntryPoint {
Expand Down Expand Up @@ -109,11 +109,12 @@ impl TransactionResources {
impl GasCosts {
pub fn create_for_testing_from_subset(subset_of_os_constants: &str) -> Self {
let subset_of_os_constants: Value = serde_json::from_str(subset_of_os_constants).unwrap();
let mut os_constants: Value = serde_json::from_str::<Value>(DEFAULT_CONSTANTS_JSON)
.unwrap()
.get("os_constants")
.unwrap()
.clone();
let mut os_constants: Value =
serde_json::from_str::<Value>(VERSIONED_CONSTANTS_LATEST_JSON)
.unwrap()
.get("os_constants")
.unwrap()
.clone();
update_json_value(&mut os_constants, subset_of_os_constants);
let os_constants: OsConstants = serde_json::from_value(os_constants).unwrap();
os_constants.gas_costs
Expand Down
59 changes: 52 additions & 7 deletions crates/blockifier/src/versioned_constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ use cairo_vm::vm::runners::cairo_runner::ExecutionResources;
use indexmap::{IndexMap, IndexSet};
use num_rational::Ratio;
use once_cell::sync::Lazy;
use paste::paste;
use serde::de::Error as DeserializationError;
use serde::{Deserialize, Deserializer};
use serde_json::{Map, Number, Value};
use strum::IntoEnumIterator;
use strum_macros::{EnumCount, EnumIter};
use thiserror::Error;

use crate::execution::deprecated_syscalls::hint_processor::SyscallCounter;
Expand All @@ -26,18 +28,56 @@ use crate::transaction::transaction_types::TransactionType;
#[path = "versioned_constants_test.rs"]
pub mod test;

pub(crate) const DEFAULT_CONSTANTS_JSON: &str =
include_str!("../resources/versioned_constants.json");
static DEFAULT_CONSTANTS: Lazy<VersionedConstants> = Lazy::new(|| {
serde_json::from_str(DEFAULT_CONSTANTS_JSON)
.expect("Versioned constants JSON file is malformed")
});
/// Auto-generate getters for listed versioned constants versions.
macro_rules! define_versioned_constants {
($(($variant:ident, $path_to_json:expr)),* $(,)?) => {
/// Enum of all the Starknet versions supporting versioned constants.
#[derive(Clone, Debug, EnumCount, EnumIter, Hash, Eq, PartialEq)]
pub enum StarknetVersion {
$($variant,)*
}

// 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 [<VERSIONED_CONSTANTS_ $variant:upper>]: Lazy<VersionedConstants> = Lazy::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 From<StarknetVersion> for &'static VersionedConstants {
fn from(version: StarknetVersion) -> Self {
match version {
$(
StarknetVersion::$variant => {
& paste! { [<VERSIONED_CONSTANTS_ $variant:upper>] }
}
)*
}
}
}
};
}

define_versioned_constants! {
(V0_13_0, "../resources/versioned_constants_13_0.json"),
(V0_13_1, "../resources/versioned_constants_13_1.json"),
(V0_13_1_1, "../resources/versioned_constants_13_1_1.json"),
(Latest, "../resources/versioned_constants.json"),
}

pub type ResourceCost = Ratio<u128>;

/// Contains constants for the Blockifier that may vary between versions.
/// Additional constants in the JSON file, not used by Blockifier but included for transparency, are
/// automatically ignored during deserialization.
/// Instances of this struct for specific Starknet versions can be selected by using the above enum.
#[derive(Clone, Debug, Default, Deserialize)]
pub struct VersionedConstants {
// Limits.
Expand Down Expand Up @@ -73,10 +113,15 @@ pub struct VersionedConstants {
}

impl VersionedConstants {
/// Get the constants for the specified Starknet version.
pub fn get(version: StarknetVersion) -> &'static Self {
version.into()
}

/// Get the constants that shipped with the current version of the Blockifier.
/// To use custom constants, initialize the struct from a file using `try_from`.
pub fn latest_constants() -> &'static Self {
&DEFAULT_CONSTANTS
Self::get(StarknetVersion::Latest)
}

/// Returns the initial gas of any transaction to run with.
Expand Down
19 changes: 14 additions & 5 deletions crates/blockifier/src/versioned_constants_test.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
use cairo_vm::types::builtin_name::BuiltinName;
use glob::glob;
use glob::{glob, Paths};
use pretty_assertions::assert_eq;

use super::*;

// TODO: Test Starknet OS validation.
// TODO: Add an unallowed field scenario for GasCost parsing.

/// Returns all JSON files in the resources directory (should be all versioned constants files).
fn all_jsons_in_dir() -> Paths {
glob(format!("{}/resources/*.json", env!("CARGO_MANIFEST_DIR")).as_str()).unwrap()
}

#[test]
fn test_successful_gas_costs_parsing() {
let json_data = r#"
Expand Down Expand Up @@ -70,7 +75,7 @@ fn get_json_value_without_defaults() -> serde_json::Value {
"max_recursion_depth": 2
}"#;
// Fill the os constants with the gas cost values (do not have a default value).
let mut os_constants: Value = serde_json::from_str::<Value>(DEFAULT_CONSTANTS_JSON)
let mut os_constants: Value = serde_json::from_str::<Value>(VERSIONED_CONSTANTS_LATEST_JSON)
.unwrap()
.get("os_constants")
.unwrap()
Expand All @@ -91,7 +96,7 @@ fn get_json_value_without_defaults() -> serde_json::Value {
#[test]
fn test_versioned_constants_base_overrides() {
// Create a versioned constants copy with a modified value for `invoke_tx_max_n_steps`.
let mut versioned_constants_base_overrides = DEFAULT_CONSTANTS.clone();
let mut versioned_constants_base_overrides = VERSIONED_CONSTANTS_LATEST.clone();
versioned_constants_base_overrides.invoke_tx_max_n_steps += 1;

let result = VersionedConstants::get_versioned_constants(VersionedConstantsOverrides {
Expand Down Expand Up @@ -218,9 +223,13 @@ fn test_invalid_number() {

#[test]
fn test_old_json_parsing() {
let files = glob(format!("{}/resources/*.json", env!("CARGO_MANIFEST_DIR")).as_str()).unwrap();
for file in files.map(Result::unwrap) {
for file in all_jsons_in_dir().map(Result::unwrap) {
serde_json::from_reader::<_, VersionedConstants>(&std::fs::File::open(&file).unwrap())
.unwrap_or_else(|_| panic!("Versioned constants JSON file {file:#?} is malformed"));
}
}

#[test]
fn test_all_jsons_in_enum() {
assert_eq!(StarknetVersion::iter().count(), all_jsons_in_dir().count());
}

0 comments on commit 08da831

Please sign in to comment.