From 6475cf150fe8f6ac452ab5aa38788af81879e2d9 Mon Sep 17 00:00:00 2001 From: AvivYossef-starkware Date: Tue, 3 Dec 2024 16:39:53 +0200 Subject: [PATCH 1/2] feat(papyrus_storage): get casm and sierra --- .../src/execution/contract_class.rs | 4 +++- .../papyrus_state_reader/src/papyrus_state.rs | 23 ++++++++++++------- crates/papyrus_storage/src/compiled_class.rs | 18 +++++++++++++++ crates/papyrus_storage/src/lib.rs | 3 +++ 4 files changed, 39 insertions(+), 9 deletions(-) diff --git a/crates/blockifier/src/execution/contract_class.rs b/crates/blockifier/src/execution/contract_class.rs index cf3d7289f9..061684e59f 100644 --- a/crates/blockifier/src/execution/contract_class.rs +++ b/crates/blockifier/src/execution/contract_class.rs @@ -21,7 +21,7 @@ use itertools::Itertools; use semver::Version; use serde::de::Error as DeserializationError; use serde::{Deserialize, Deserializer, Serialize}; -use starknet_api::contract_class::{ContractClass, EntryPointType}; +use starknet_api::contract_class::{ContractClass, EntryPointType, SierraVersion}; use starknet_api::core::EntryPointSelector; use starknet_api::deprecated_contract_class::{ ContractClass as DeprecatedContractClass, @@ -68,6 +68,8 @@ pub enum RunnableCompiledClass { V1Native(NativeCompiledClassV1), } +pub type VersionedRunnableCompiledClass = (RunnableCompiledClass, SierraVersion); + impl TryFrom for RunnableCompiledClass { type Error = ProgramError; diff --git a/crates/papyrus_state_reader/src/papyrus_state.rs b/crates/papyrus_state_reader/src/papyrus_state.rs index 2af2651d10..8f2a8bb9d8 100644 --- a/crates/papyrus_state_reader/src/papyrus_state.rs +++ b/crates/papyrus_state_reader/src/papyrus_state.rs @@ -2,6 +2,7 @@ use blockifier::execution::contract_class::{ CompiledClassV0, CompiledClassV1, RunnableCompiledClass, + VersionedRunnableCompiledClass, }; use blockifier::state::errors::StateError; use blockifier::state::global_cache::GlobalContractCache; @@ -11,6 +12,7 @@ use papyrus_storage::db::RO; use papyrus_storage::state::StateStorageReader; use papyrus_storage::StorageReader; use starknet_api::block::BlockNumber; +use starknet_api::contract_class::SierraVersion; use starknet_api::core::{ClassHash, CompiledClassHash, ContractAddress, Nonce}; use starknet_api::state::{StateNumber, StorageKey}; use starknet_types_core::felt::Felt; @@ -46,7 +48,7 @@ impl PapyrusReader { fn get_compiled_class_inner( &self, class_hash: ClassHash, - ) -> StateResult { + ) -> StateResult { let state_number = StateNumber(self.latest_block); let class_declaration_block_number = self .reader()? @@ -57,16 +59,20 @@ impl PapyrusReader { Some(block_number) if block_number <= state_number.0); if class_is_declared { - let casm_compiled_class = self + let (casm_compiled_class, sierra) = self .reader()? - .get_casm(&class_hash) + .get_casm_and_sierra(&class_hash) .map_err(|err| StateError::StateReadError(err.to_string()))? .expect( "Should be able to fetch a Casm class if its definition exists, database is \ inconsistent.", ); + let sierra_version = SierraVersion::extract_from_program(&sierra.sierra_program)?; - return Ok(RunnableCompiledClass::V1(CompiledClassV1::try_from(casm_compiled_class)?)); + return Ok(( + RunnableCompiledClass::V1(CompiledClassV1::try_from(casm_compiled_class)?), + sierra_version, + )); } let v0_compiled_class = self @@ -76,9 +82,10 @@ impl PapyrusReader { .map_err(|err| StateError::StateReadError(err.to_string()))?; match v0_compiled_class { - Some(starknet_api_contract_class) => { - Ok(CompiledClassV0::try_from(starknet_api_contract_class)?.into()) - } + Some(starknet_api_contract_class) => Ok(( + CompiledClassV0::try_from(starknet_api_contract_class)?.into(), + SierraVersion::zero(), + )), None => Err(StateError::UndeclaredClassHash(class_hash)), } } @@ -131,7 +138,7 @@ impl StateReader for PapyrusReader { match contract_class { Some(contract_class) => Ok(contract_class), None => { - let contract_class_from_db = self.get_compiled_class_inner(class_hash)?; + let (contract_class_from_db, _) = self.get_compiled_class_inner(class_hash)?; // The class was declared in a previous (finalized) state; update the global cache. self.global_class_hash_to_class.set(class_hash, contract_class_from_db.clone()); Ok(contract_class_from_db) diff --git a/crates/papyrus_storage/src/compiled_class.rs b/crates/papyrus_storage/src/compiled_class.rs index d0e2b656aa..14ae9199a3 100644 --- a/crates/papyrus_storage/src/compiled_class.rs +++ b/crates/papyrus_storage/src/compiled_class.rs @@ -50,7 +50,9 @@ use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; use papyrus_proc_macros::latency_histogram; use starknet_api::block::BlockNumber; use starknet_api::core::ClassHash; +use starknet_api::state::SierraContractClass; +use crate::class::ClassStorageReader; use crate::db::serialization::VersionZeroWrapper; use crate::db::table_types::{SimpleTable, Table}; use crate::db::{DbTransaction, TableHandle, TransactionKind, RW}; @@ -61,6 +63,12 @@ use crate::{FileHandlers, MarkerKind, MarkersTable, OffsetKind, StorageResult, S pub trait CasmStorageReader { /// Returns the Cairo assembly of a class given its Sierra class hash. fn get_casm(&self, class_hash: &ClassHash) -> StorageResult>; + /// Returns the Cairo assembly of a class and its sierra contract class given its Sierra class + /// hash. + fn get_casm_and_sierra( + &self, + class_hash: &ClassHash, + ) -> StorageResult>; /// The block marker is the first block number that doesn't exist yet. /// /// Note: If the last blocks don't contain any declared classes, the marker will point at the @@ -85,6 +93,16 @@ impl CasmStorageReader for StorageTxn<'_, Mode> { casm_location.map(|location| self.file_handlers.get_casm_unchecked(location)).transpose() } + fn get_casm_and_sierra( + &self, + class_hash: &ClassHash, + ) -> StorageResult> { + match (self.get_casm(class_hash)?, self.get_class(class_hash)?) { + (Some(casm), Some(sierra)) => Ok(Some((casm, sierra))), + (_, _) => Ok(None), + } + } + fn get_compiled_class_marker(&self) -> StorageResult { let markers_table = self.open_table(&self.tables.markers)?; Ok(markers_table.get(&self.txn, &MarkerKind::CompiledClass)?.unwrap_or_default()) diff --git a/crates/papyrus_storage/src/lib.rs b/crates/papyrus_storage/src/lib.rs index df7bdcecda..4fe3914e8f 100644 --- a/crates/papyrus_storage/src/lib.rs +++ b/crates/papyrus_storage/src/lib.rs @@ -127,6 +127,7 @@ use starknet_api::core::{ClassHash, ContractAddress, Nonce}; use starknet_api::deprecated_contract_class::ContractClass as DeprecatedContractClass; use starknet_api::state::{SierraContractClass, StateNumber, StorageKey, ThinStateDiff}; use starknet_api::transaction::{Transaction, TransactionHash, TransactionOutput}; +use starknet_api::StarknetApiError; use starknet_types_core::felt::Felt; use tracing::{debug, warn}; use validator::Validate; @@ -590,6 +591,8 @@ pub enum StorageError { #[error("The table {table_name} is unused under the {storage_scope:?} storage scope.")] ScopeError { table_name: String, storage_scope: StorageScope }, #[error(transparent)] + StarknetApiError(#[from] StarknetApiError), + #[error(transparent)] IOError(#[from] std::io::Error), #[error(transparent)] SerdeError(#[from] serde_json::Error), From 9325c6eaa78205bd8e4c70ad66f7a6c28229d979 Mon Sep 17 00:00:00 2001 From: AvivYossef-starkware Date: Tue, 3 Dec 2024 11:47:21 +0200 Subject: [PATCH 2/2] refactor(blockifier): min compiler version for sierra gas type --- crates/blockifier/src/execution/contract_class.rs | 8 ++++---- crates/blockifier/src/execution/contract_class_test.rs | 2 +- crates/blockifier/src/versioned_constants.rs | 3 ++- crates/starknet_api/src/contract_class.rs | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/crates/blockifier/src/execution/contract_class.rs b/crates/blockifier/src/execution/contract_class.rs index 061684e59f..c8bb2712c2 100644 --- a/crates/blockifier/src/execution/contract_class.rs +++ b/crates/blockifier/src/execution/contract_class.rs @@ -21,7 +21,7 @@ use itertools::Itertools; use semver::Version; use serde::de::Error as DeserializationError; use serde::{Deserialize, Deserializer, Serialize}; -use starknet_api::contract_class::{ContractClass, EntryPointType, SierraVersion}; +use starknet_api::contract_class::{ContractClass, EntryPointType, SierraVersion, VersionedCasm}; use starknet_api::core::EntryPointSelector; use starknet_api::deprecated_contract_class::{ ContractClass as DeprecatedContractClass, @@ -134,7 +134,7 @@ impl RunnableCompiledClass { /// Returns whether this contract should run using Cairo steps or Sierra gas. pub fn tracked_resource( &self, - min_sierra_version: &CompilerVersion, + min_sierra_version: &SierraVersion, gas_mode: GasVectorComputationMode, ) -> TrackedResource { match gas_mode { @@ -264,8 +264,8 @@ impl CompiledClassV1 { } /// Returns whether this contract should run using Cairo steps or Sierra gas. - pub fn tracked_resource(&self, min_sierra_version: &CompilerVersion) -> TrackedResource { - if *min_sierra_version <= self.compiler_version { + pub fn tracked_resource(&self, min_sierra_version: &SierraVersion) -> TrackedResource { + if *min_sierra_version <= self.sierra_version { TrackedResource::SierraGas } else { TrackedResource::CairoSteps diff --git a/crates/blockifier/src/execution/contract_class_test.rs b/crates/blockifier/src/execution/contract_class_test.rs index bbf9bedc6c..15a76af858 100644 --- a/crates/blockifier/src/execution/contract_class_test.rs +++ b/crates/blockifier/src/execution/contract_class_test.rs @@ -14,7 +14,7 @@ fn test_get_visited_segments() { program: Default::default(), entry_points_by_type: Default::default(), hints: Default::default(), - compiler_version: Default::default(), + sierra_version: Default::default(), bytecode_segment_lengths: NestedIntList::Node(vec![ NestedIntList::Leaf(151), NestedIntList::Leaf(104), diff --git a/crates/blockifier/src/versioned_constants.rs b/crates/blockifier/src/versioned_constants.rs index 85f61f483a..ab37525691 100644 --- a/crates/blockifier/src/versioned_constants.rs +++ b/crates/blockifier/src/versioned_constants.rs @@ -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::contract_class::SierraVersion; use starknet_api::core::ContractAddress; use starknet_api::execution_resources::{GasAmount, GasVector}; use starknet_api::transaction::fields::GasVectorComputationMode; @@ -183,7 +184,7 @@ pub struct VersionedConstants { pub max_recursion_depth: usize, pub validate_max_n_steps: u32, pub validate_max_sierra_gas: GasAmount, - pub min_compiler_version_for_sierra_gas: CompilerVersion, + pub min_compiler_version_for_sierra_gas: SierraVersion, // BACKWARD COMPATIBILITY: If true, the segment_arena builtin instance counter will be // multiplied by 3. This offsets a bug in the old vm where the counter counted the number of // cells used by instances of the builtin, instead of the number of instances. diff --git a/crates/starknet_api/src/contract_class.rs b/crates/starknet_api/src/contract_class.rs index 86445cd26f..92752bf9cd 100644 --- a/crates/starknet_api/src/contract_class.rs +++ b/crates/starknet_api/src/contract_class.rs @@ -48,7 +48,7 @@ impl ContractClass { } } -#[derive(Deref, Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] +#[derive(Deref, Serialize, Deserialize, Clone, Debug, Eq, PartialEq, PartialOrd)] pub struct SierraVersion(Version); impl SierraVersion {