diff --git a/crates/papyrus_storage/src/compiled_class.rs b/crates/papyrus_storage/src/compiled_class.rs index d0e2b656aa0..b8dc8342a1b 100644 --- a/crates/papyrus_storage/src/compiled_class.rs +++ b/crates/papyrus_storage/src/compiled_class.rs @@ -49,8 +49,10 @@ mod casm_test; use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; use papyrus_proc_macros::latency_histogram; use starknet_api::block::BlockNumber; +use starknet_api::contract_class::{SierraVersion, VersionedCasm}; use starknet_api::core::ClassHash; +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,8 @@ 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 version given its Sierra class hash. + fn get_versioned_casm(&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 +89,18 @@ impl CasmStorageReader for StorageTxn<'_, Mode> { casm_location.map(|location| self.file_handlers.get_casm_unchecked(location)).transpose() } + fn get_versioned_casm(&self, class_hash: &ClassHash) -> StorageResult> { + // TODO(Aviv): Consider adding a dedicated table to store Sierra versions for better + // organization and performance. + match (self.get_casm(class_hash)?, self.get_class(class_hash)?) { + (Some(casm), Some(sierra)) => { + let sierra_version = SierraVersion::extract_from_program(&sierra.sierra_program)?; + Ok(Some((casm, sierra_version))) + } + (_, _) => 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 df7bdcecdaa..4fe3914e8f0 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), diff --git a/crates/papyrus_storage/src/serialization/serializers.rs b/crates/papyrus_storage/src/serialization/serializers.rs index 8daf2510c2b..710674cb516 100644 --- a/crates/papyrus_storage/src/serialization/serializers.rs +++ b/crates/papyrus_storage/src/serialization/serializers.rs @@ -28,7 +28,7 @@ use starknet_api::block::{ GasPricePerToken, StarknetVersion, }; -use starknet_api::contract_class::EntryPointType; +use starknet_api::contract_class::{EntryPointType, SierraVersion}; use starknet_api::core::{ ClassHash, CompiledClassHash, @@ -745,6 +745,16 @@ impl StorageSerde for String { } } +impl StorageSerde for SierraVersion { + fn serialize_into(&self, res: &mut impl std::io::Write) -> Result<(), StorageSerdeError> { + serde_json::to_value(self)?.serialize_into(res) + } + + fn deserialize_from(bytes: &mut impl std::io::Read) -> Option { + serde_json::from_value(serde_json::Value::deserialize_from(bytes)?).ok() + } +} + impl StorageSerde for Option { fn serialize_into(&self, res: &mut impl std::io::Write) -> Result<(), StorageSerdeError> { match self { diff --git a/crates/starknet_api/src/contract_class.rs b/crates/starknet_api/src/contract_class.rs index 86445cd26fa..7b15bbe7c70 100644 --- a/crates/starknet_api/src/contract_class.rs +++ b/crates/starknet_api/src/contract_class.rs @@ -120,6 +120,9 @@ impl FromStr for SierraVersion { } } +/// A tuple of a CasmContractClass and a Sierra Version. +pub type VersionedCasm = (CasmContractClass, SierraVersion); + /// All relevant information about a declared contract class, including the compiled contract class /// and other parameters derived from the original declare transaction required for billing. #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]