diff --git a/crates/papyrus_rpc/src/v0_8/api/api_impl.rs b/crates/papyrus_rpc/src/v0_8/api/api_impl.rs index ad9094da1a..1c8984e7cb 100644 --- a/crates/papyrus_rpc/src/v0_8/api/api_impl.rs +++ b/crates/papyrus_rpc/src/v0_8/api/api_impl.rs @@ -21,6 +21,7 @@ use papyrus_storage::db::{TransactionKind, RO}; use papyrus_storage::state::StateStorageReader; use papyrus_storage::{StorageError, StorageReader, StorageTxn}; use starknet_api::block::{BlockHash, BlockHeaderWithoutHash, BlockNumber, BlockStatus}; +use starknet_api::contract_class::SierraVersion; use starknet_api::core::{ ChainId, ClassHash, @@ -142,6 +143,7 @@ use crate::{ get_block_status, get_latest_block_number, internal_server_error, + internal_server_error_with_msg, verify_storage_scope, ContinuationTokenAsStruct, GENESIS_HASH, @@ -1449,7 +1451,7 @@ impl JsonRpcServer for JsonRpcServerImpl { &self, block_id: BlockId, class_hash: ClassHash, - ) -> RpcResult { + ) -> RpcResult<(CompiledContractClass, SierraVersion)> { let storage_txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?; let state_reader = storage_txn.get_state_reader().map_err(internal_server_error)?; let block_number = get_accepted_block_number(&storage_txn, block_id)?; @@ -1462,11 +1464,17 @@ impl JsonRpcServer for JsonRpcServerImpl { if class_definition_block_number > block_number { return Err(ErrorObjectOwned::from(CLASS_HASH_NOT_FOUND)); } - let casm = storage_txn - .get_casm(&class_hash) - .map_err(internal_server_error)? + let (option_casm, option_sierra) = storage_txn + .get_casm_and_sierra(&class_hash) + .map_err(internal_server_error_with_msg)?; + + // Check if both options are `Some`. + let (casm, sierra) = option_casm + .zip(option_sierra) .ok_or_else(|| ErrorObjectOwned::from(CLASS_HASH_NOT_FOUND))?; - return Ok(CompiledContractClass::V1(casm)); + let sierra_version = SierraVersion::extract_from_program(&sierra.sierra_program) + .map_err(internal_server_error_with_msg)?; + return Ok((CompiledContractClass::V1(casm), sierra_version)); } // Check if this class exists in the Cairo0 classes table. @@ -1476,7 +1484,10 @@ impl JsonRpcServer for JsonRpcServerImpl { .get_deprecated_class_definition_at(state_number, &class_hash) .map_err(internal_server_error)? .ok_or_else(|| ErrorObjectOwned::from(CLASS_HASH_NOT_FOUND))?; - Ok(CompiledContractClass::V0(deprecated_compiled_contract_class)) + Ok(( + CompiledContractClass::V0(deprecated_compiled_contract_class), + SierraVersion::DEPRECATED, + )) } } diff --git a/crates/papyrus_rpc/src/v0_8/api/mod.rs b/crates/papyrus_rpc/src/v0_8/api/mod.rs index 5e45ff1386..5fb8f71948 100644 --- a/crates/papyrus_rpc/src/v0_8/api/mod.rs +++ b/crates/papyrus_rpc/src/v0_8/api/mod.rs @@ -264,7 +264,7 @@ pub trait JsonRpc { &self, block_id: BlockId, class_hash: ClassHash, - ) -> RpcResult; + ) -> RpcResult<(CompiledContractClass, SierraVersion)>; } #[derive(Debug, Clone, Deserialize, Serialize)] diff --git a/crates/papyrus_rpc/src/v0_8/api/test.rs b/crates/papyrus_rpc/src/v0_8/api/test.rs index fe2b144322..e08d424aba 100644 --- a/crates/papyrus_rpc/src/v0_8/api/test.rs +++ b/crates/papyrus_rpc/src/v0_8/api/test.rs @@ -52,6 +52,7 @@ use starknet_api::block::{ GasPricePerToken, StarknetVersion, }; +use starknet_api::contract_class::SierraVersion; use starknet_api::core::{ ClassHash, CompiledClassHash, @@ -3688,6 +3689,9 @@ async fn get_compiled_class() { JsonRpcServerImpl, >(None, None, None, None, None); let cairo1_contract_class = CasmContractClass::get_test_instance(&mut get_rng()); + // We need to save the Sierra component of the Cairo 1 contract in storage to maintain + // consistency. + let sierra_contract_class = StarknetApiContractClass::default(); let cairo0_contract_class = StarknetApiDeprecatedContractClass::get_test_instance(&mut get_rng()); storage_writer @@ -3709,28 +3713,34 @@ async fn get_compiled_class() { .unwrap() // Note: there is no need to write the cairo1 contract class here because the // declared_classes_table is not used in the rpc method. - .append_classes(BlockNumber(0), &[], &[(cairo0_class_hash, &cairo0_contract_class)]) + .append_classes(BlockNumber(0), &[(cairo1_class_hash, &sierra_contract_class)], &[(cairo0_class_hash, &cairo0_contract_class)]) .unwrap() .commit() .unwrap(); let res = module - .call::<_, CompiledContractClass>( + .call::<_, (CompiledContractClass, SierraVersion)>( method_name, (BlockId::Tag(Tag::Latest), cairo1_class_hash), ) .await .unwrap(); - assert_eq!(res, CompiledContractClass::V1(cairo1_contract_class)); + assert_eq!( + res, + ( + CompiledContractClass::V1(cairo1_contract_class), + SierraVersion::extract_from_program(&sierra_contract_class.sierra_program).unwrap() + ) + ); let res = module - .call::<_, CompiledContractClass>( + .call::<_, (CompiledContractClass, SierraVersion)>( method_name, (BlockId::Tag(Tag::Latest), cairo0_class_hash), ) .await .unwrap(); - assert_eq!(res, CompiledContractClass::V0(cairo0_contract_class)); + assert_eq!(res, (CompiledContractClass::V0(cairo0_contract_class), SierraVersion::DEPRECATED)); // Ask for an invalid class hash, which does no exist in the table. let err = module diff --git a/crates/starknet_gateway/src/rpc_state_reader.rs b/crates/starknet_gateway/src/rpc_state_reader.rs index a01ccdc703..62e637a292 100644 --- a/crates/starknet_gateway/src/rpc_state_reader.rs +++ b/crates/starknet_gateway/src/rpc_state_reader.rs @@ -10,6 +10,7 @@ use reqwest::blocking::Client as BlockingClient; use serde::Serialize; use serde_json::{json, Value}; use starknet_api::block::{BlockInfo, BlockNumber}; +use starknet_api::contract_class::SierraVersion; use starknet_api::core::{ClassHash, CompiledClassHash, ContractAddress, Nonce}; use starknet_api::state::StorageKey; use starknet_types_core::felt::Felt; @@ -144,7 +145,7 @@ impl BlockifierStateReader for RpcStateReader { let result = self.send_rpc_request("starknet_getCompiledContractClass", get_compiled_class_params)?; - let contract_class: CompiledContractClass = + let (contract_class, _): (CompiledContractClass, SierraVersion) = serde_json::from_value(result).map_err(serde_err_to_state_err)?; match contract_class { CompiledContractClass::V1(contract_class_v1) => Ok(RunnableCompiledClass::V1( diff --git a/crates/starknet_gateway/src/rpc_state_reader_test.rs b/crates/starknet_gateway/src/rpc_state_reader_test.rs index 623c049427..514518636a 100644 --- a/crates/starknet_gateway/src/rpc_state_reader_test.rs +++ b/crates/starknet_gateway/src/rpc_state_reader_test.rs @@ -6,6 +6,7 @@ use papyrus_rpc::CompiledContractClass; use serde::Serialize; use serde_json::json; use starknet_api::block::{BlockInfo, BlockNumber}; +use starknet_api::contract_class::SierraVersion; use starknet_api::{class_hash, contract_address, felt, nonce}; use crate::config::RpcStateReaderConfig; @@ -178,8 +179,11 @@ async fn test_get_compiled_class() { "starknet_getCompiledContractClass", GetCompiledClassParams { block_id: BlockId::Latest, class_hash: class_hash!("0x1") }, &RpcResponse::Success(RpcSuccessResponse { - result: serde_json::to_value(CompiledContractClass::V1(expected_result.clone())) - .unwrap(), + result: serde_json::to_value(( + CompiledContractClass::V1(expected_result.clone()), + SierraVersion::default(), + )) + .unwrap(), ..Default::default() }), );