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)]