From 6df3e214b211dbfb6e4b0895b9c4063ea71eb8ea Mon Sep 17 00:00:00 2001 From: amos rothberg Date: Fri, 21 Jun 2024 16:15:54 +0300 Subject: [PATCH] feat: added private versioned constants --- crates/blockifier/src/versioned_constants.rs | 34 ++++++++++++ .../src/versioned_constants_test.rs | 20 +++++++ crates/native_blockifier/src/lib.rs | 2 + .../src/py_block_executor.rs | 13 ++--- crates/native_blockifier/src/py_objects.rs | 54 +++++++++++++++++++ crates/native_blockifier/src/py_validator.rs | 12 ++--- 6 files changed, 120 insertions(+), 15 deletions(-) diff --git a/crates/blockifier/src/versioned_constants.rs b/crates/blockifier/src/versioned_constants.rs index aa5d9a3abd..a44b05296a 100644 --- a/crates/blockifier/src/versioned_constants.rs +++ b/crates/blockifier/src/versioned_constants.rs @@ -202,6 +202,34 @@ impl VersionedConstants { ) -> Self { Self { validate_max_n_steps, max_recursion_depth, ..Self::latest_constants().clone() } } + + // TODO(Amos, 1/8/2024): Remove the explicit `validate_max_n_steps` & `max_recursion_depth`, + // they should be part of the general override. + /// `versioned_constants_base_overrides` are used if they are provided, otherwise the latest + /// versioned constants are used. `validate_max_n_steps` & `max_recursion_depth` override both. + pub fn get_versioned_constants( + versioned_constants_overrides: VersionedConstantsOverrides, + ) -> Self { + let VersionedConstantsOverrides { + validate_max_n_steps, + max_recursion_depth, + versioned_constants_base_overrides, + } = versioned_constants_overrides; + let base_overrides = match versioned_constants_base_overrides { + Some(versioned_constants_base_overrides) => { + log::debug!( + "Using provided `versioned_constants_base_overrides` (with additional \ + overrides)." + ); + versioned_constants_base_overrides + } + None => { + log::debug!("Using latest versioned constants (with additional overrides)."); + Self::latest_constants().clone() + } + }; + Self { validate_max_n_steps, max_recursion_depth, ..base_overrides } + } } impl TryFrom<&Path> for VersionedConstants { @@ -690,3 +718,9 @@ pub struct ResourcesByVersion { pub resources: ResourcesParams, pub deprecated_resources: ResourcesParams, } + +pub struct VersionedConstantsOverrides { + pub validate_max_n_steps: u32, + pub max_recursion_depth: usize, + pub versioned_constants_base_overrides: Option, +} diff --git a/crates/blockifier/src/versioned_constants_test.rs b/crates/blockifier/src/versioned_constants_test.rs index 87bf080ae7..d449dff959 100644 --- a/crates/blockifier/src/versioned_constants_test.rs +++ b/crates/blockifier/src/versioned_constants_test.rs @@ -86,6 +86,26 @@ fn get_json_value_without_defaults() -> serde_json::Value { json_value_without_defaults } +/// Assert `versioned_constants_base_overrides` are used when provided. +#[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(); + versioned_constants_base_overrides.invoke_tx_max_n_steps += 1; + + let result = VersionedConstants::get_versioned_constants(VersionedConstantsOverrides { + validate_max_n_steps: versioned_constants_base_overrides.validate_max_n_steps, + max_recursion_depth: versioned_constants_base_overrides.max_recursion_depth, + versioned_constants_base_overrides: Some(versioned_constants_base_overrides.clone()), + }); + + // Assert the new value is used. + assert_eq!( + result.invoke_tx_max_n_steps, + versioned_constants_base_overrides.invoke_tx_max_n_steps + ); +} + #[test] fn test_default_values() { let json_value_without_defaults = get_json_value_without_defaults(); diff --git a/crates/native_blockifier/src/lib.rs b/crates/native_blockifier/src/lib.rs index 4dc4a0f476..1ae8dd5464 100644 --- a/crates/native_blockifier/src/lib.rs +++ b/crates/native_blockifier/src/lib.rs @@ -32,6 +32,7 @@ use py_validator::PyValidator; use pyo3::prelude::*; use storage::StorageConfig; +use crate::py_objects::PyVersionedConstantsOverrides; use crate::py_state_diff::PyStateDiff; use crate::py_testing_wrappers::{ estimate_casm_hash_computation_resources_for_testing_list, @@ -47,6 +48,7 @@ fn native_blockifier(py: Python<'_>, py_module: &PyModule) -> PyResult<()> { py_module.add_class::()?; py_module.add_class::()?; py_module.add_class::()?; + py_module.add_class::()?; py_module.add_class::()?; py_module.add_class::()?; py_module.add("UndeclaredClassHashError", py.get_type::())?; diff --git a/crates/native_blockifier/src/py_block_executor.rs b/crates/native_blockifier/src/py_block_executor.rs index 4d4a33f13c..69ffa0557b 100644 --- a/crates/native_blockifier/src/py_block_executor.rs +++ b/crates/native_blockifier/src/py_block_executor.rs @@ -21,7 +21,7 @@ use starknet_api::hash::StarkFelt; use starknet_api::transaction::Fee; use crate::errors::{NativeBlockifierError, NativeBlockifierResult}; -use crate::py_objects::{PyBouncerConfig, PyConcurrencyConfig}; +use crate::py_objects::{PyBouncerConfig, PyConcurrencyConfig, PyVersionedConstantsOverrides}; use crate::py_state_diff::{PyBlockInfo, PyStateDiff}; use crate::py_transaction::{py_tx, PyClassInfo, PY_TX_PARSING_ERR}; use crate::py_utils::{int_to_chain_id, into_block_number_hash_pair, PyFelt}; @@ -91,23 +91,20 @@ pub struct PyBlockExecutor { #[pymethods] impl PyBlockExecutor { #[new] - #[pyo3(signature = (bouncer_config, concurrency_config, general_config, validate_max_n_steps, max_recursion_depth, global_contract_cache_size, target_storage_config))] + #[pyo3(signature = (bouncer_config, concurrency_config, general_config, global_contract_cache_size, target_storage_config, py_versioned_constants_overrides))] pub fn create( bouncer_config: PyBouncerConfig, concurrency_config: PyConcurrencyConfig, general_config: PyGeneralConfig, - validate_max_n_steps: u32, - max_recursion_depth: usize, global_contract_cache_size: usize, target_storage_config: StorageConfig, + py_versioned_constants_overrides: PyVersionedConstantsOverrides, ) -> Self { log::debug!("Initializing Block Executor..."); let storage = PapyrusStorage::new(target_storage_config).expect("Failed to initialize storage."); - let versioned_constants = VersionedConstants::latest_constants_with_overrides( - validate_max_n_steps, - max_recursion_depth, - ); + let versioned_constants = + VersionedConstants::get_versioned_constants(py_versioned_constants_overrides.into()); log::debug!("Initialized Block Executor."); Self { diff --git a/crates/native_blockifier/src/py_objects.rs b/crates/native_blockifier/src/py_objects.rs index ac5c2da789..a8027c4059 100644 --- a/crates/native_blockifier/src/py_objects.rs +++ b/crates/native_blockifier/src/py_objects.rs @@ -3,7 +3,9 @@ use std::collections::HashMap; use blockifier::abi::constants; use blockifier::blockifier::config::ConcurrencyConfig; use blockifier::bouncer::{BouncerConfig, BouncerWeights, BuiltinCount}; +use blockifier::versioned_constants::{VersionedConstants, VersionedConstantsOverrides}; use cairo_vm::vm::runners::cairo_runner::ExecutionResources; +use pyo3::exceptions::PyValueError; use pyo3::prelude::*; // From Rust to Python. @@ -31,6 +33,58 @@ impl From for PyExecutionResources { // From Python to Rust. +#[pyclass] +#[derive(Clone)] +pub struct PyVersionedConstantsOverrides { + pub validate_max_n_steps: u32, + pub max_recursion_depth: usize, + pub versioned_constants_base_overrides: Option, +} + +#[pymethods] +impl PyVersionedConstantsOverrides { + #[new] + #[pyo3(signature = (validate_max_n_steps, max_recursion_depth, versioned_constants_base_overrides))] + pub fn create( + validate_max_n_steps: u32, + max_recursion_depth: usize, + versioned_constants_base_overrides: Option, + ) -> Self { + Self { validate_max_n_steps, max_recursion_depth, versioned_constants_base_overrides } + } + + #[staticmethod] + pub fn assert_versioned_consts_load_successfully( + versioned_constants_str: &str, + ) -> PyResult<()> { + if serde_json::from_str::(versioned_constants_str).is_ok() { + Ok(()) + } else { + Err(PyValueError::new_err("Failed to parse `versioned_constants_str`.")) + } + } +} + +impl From for VersionedConstantsOverrides { + fn from(py_versioned_constants_overrides: PyVersionedConstantsOverrides) -> Self { + let PyVersionedConstantsOverrides { + validate_max_n_steps, + max_recursion_depth, + versioned_constants_base_overrides, + } = py_versioned_constants_overrides; + let base_overrides = + versioned_constants_base_overrides.map(|versioned_constants_base_overrides| { + serde_json::from_str(&versioned_constants_base_overrides) + .expect("Versioned constants JSON file is malformed.") + }); + Self { + validate_max_n_steps, + max_recursion_depth, + versioned_constants_base_overrides: base_overrides, + } + } +} + #[derive(Clone, Debug, FromPyObject)] pub struct PyBouncerConfig { pub full_total_weights_with_keccak: HashMap, diff --git a/crates/native_blockifier/src/py_validator.rs b/crates/native_blockifier/src/py_validator.rs index 5e986d1280..23e80f47cc 100644 --- a/crates/native_blockifier/src/py_validator.rs +++ b/crates/native_blockifier/src/py_validator.rs @@ -9,6 +9,7 @@ use starknet_api::transaction::TransactionHash; use crate::errors::NativeBlockifierResult; use crate::py_block_executor::PyGeneralConfig; +use crate::py_objects::PyVersionedConstantsOverrides; use crate::py_state_diff::PyBlockInfo; use crate::py_transaction::{py_account_tx, PyClassInfo, PY_TX_PARSING_ERR}; use crate::py_utils::PyFelt; @@ -22,24 +23,21 @@ pub struct PyValidator { #[pymethods] impl PyValidator { #[new] - #[pyo3(signature = (general_config, state_reader_proxy, next_block_info, validate_max_n_steps, max_recursion_depth, max_nonce_for_validation_skip))] + #[pyo3(signature = (general_config, state_reader_proxy, next_block_info, max_nonce_for_validation_skip, py_versioned_constants_overrides))] pub fn create( general_config: PyGeneralConfig, state_reader_proxy: &PyAny, next_block_info: PyBlockInfo, - validate_max_n_steps: u32, - max_recursion_depth: usize, max_nonce_for_validation_skip: PyFelt, + py_versioned_constants_overrides: PyVersionedConstantsOverrides, ) -> NativeBlockifierResult { // Create the state. let state_reader = PyStateReader::new(state_reader_proxy); let state = CachedState::new(state_reader); // Create the block context. - let versioned_constants = VersionedConstants::latest_constants_with_overrides( - validate_max_n_steps, - max_recursion_depth, - ); + let versioned_constants = + VersionedConstants::get_versioned_constants(py_versioned_constants_overrides.into()); let block_context = BlockContext::new( next_block_info.try_into().expect("Failed to convert block info."), general_config.starknet_os_config.into_chain_info(),