From 4022be4c33d5a04236c660f87a2b1eea840b8b88 Mon Sep 17 00:00:00 2001 From: AvivYossef-starkware Date: Tue, 3 Dec 2024 11:47:21 +0200 Subject: [PATCH] refactor(blockifier): refactor blockifier contract class --- .../cairo_steps_test_contract.sierra.json | 2 +- .../resources/versioned_constants_0_13_0.json | 4 +-- .../resources/versioned_constants_0_13_1.json | 4 +-- .../versioned_constants_0_13_1_1.json | 4 +-- .../resources/versioned_constants_0_13_2.json | 4 +-- .../versioned_constants_0_13_2_1.json | 4 +-- .../resources/versioned_constants_0_13_3.json | 4 +-- .../resources/versioned_constants_0_13_4.json | 2 +- .../src/execution/contract_class.rs | 29 ++++++++-------- .../src/execution/contract_class_test.rs | 2 +- .../src/execution/execution_utils.rs | 2 +- .../syscalls/syscall_tests/library_call.rs | 2 +- crates/blockifier/src/test_utils/contracts.rs | 7 ++-- .../blockifier/src/test_utils/struct_impls.rs | 14 +++++++- .../src/transaction/transactions_test.rs | 14 ++++---- crates/blockifier/src/versioned_constants.rs | 3 +- .../feature_contracts_compatibility_test.rs | 33 ++++++++++--------- .../src/state_reader/compile.rs | 3 +- .../src/py_block_executor_test.rs | 10 ++++-- .../papyrus_execution/src/execution_utils.rs | 11 ++++--- crates/papyrus_execution/src/lib.rs | 4 +-- crates/papyrus_execution/src/state_reader.rs | 7 ++-- .../src/state_reader_test.rs | 13 +++++--- .../papyrus_state_reader/src/papyrus_state.rs | 8 +++-- crates/starknet_api/src/contract_class.rs | 10 +++--- crates/starknet_gateway/src/compilation.rs | 5 +-- .../starknet_gateway/src/rpc_state_reader.rs | 5 +-- .../src/rpc_state_reader_test.rs | 7 +++- 28 files changed, 127 insertions(+), 90 deletions(-) diff --git a/crates/blockifier/feature_contracts/cairo1/sierra/cairo_steps_test_contract.sierra.json b/crates/blockifier/feature_contracts/cairo1/sierra/cairo_steps_test_contract.sierra.json index 92c3efe5a3b..60eac8fd07c 100644 --- a/crates/blockifier/feature_contracts/cairo1/sierra/cairo_steps_test_contract.sierra.json +++ b/crates/blockifier/feature_contracts/cairo1/sierra/cairo_steps_test_contract.sierra.json @@ -1,7 +1,7 @@ { "sierra_program": [ "0x1", - "0x6", + "0x5", "0x0", "0x2", "0x7", diff --git a/crates/blockifier/resources/versioned_constants_0_13_0.json b/crates/blockifier/resources/versioned_constants_0_13_0.json index 1407a6a7fa4..c35c6a4b9d0 100644 --- a/crates/blockifier/resources/versioned_constants_0_13_0.json +++ b/crates/blockifier/resources/versioned_constants_0_13_0.json @@ -567,7 +567,7 @@ }, "validate_max_n_steps": 1000000, "validate_max_sierra_gas": 10000000000, - "min_compiler_version_for_sierra_gas": "100.0.0", + "min_sierra_version_for_sierra_gas": "100.0.0", "vm_resource_fee_cost": { "builtins": { "add_mod_builtin": [ @@ -620,4 +620,4 @@ 1000 ] } -} +} \ No newline at end of file diff --git a/crates/blockifier/resources/versioned_constants_0_13_1.json b/crates/blockifier/resources/versioned_constants_0_13_1.json index 56c7cc52031..a5685350474 100644 --- a/crates/blockifier/resources/versioned_constants_0_13_1.json +++ b/crates/blockifier/resources/versioned_constants_0_13_1.json @@ -603,7 +603,7 @@ }, "validate_max_n_steps": 1000000, "validate_max_sierra_gas": 10000000000, - "min_compiler_version_for_sierra_gas": "100.0.0", + "min_sierra_version_for_sierra_gas": "100.0.0", "vm_resource_fee_cost": { "builtins": { "add_mod_builtin": [ @@ -656,4 +656,4 @@ 10000 ] } -} +} \ No newline at end of file diff --git a/crates/blockifier/resources/versioned_constants_0_13_1_1.json b/crates/blockifier/resources/versioned_constants_0_13_1_1.json index ede36b46e01..9f71c758955 100644 --- a/crates/blockifier/resources/versioned_constants_0_13_1_1.json +++ b/crates/blockifier/resources/versioned_constants_0_13_1_1.json @@ -603,7 +603,7 @@ }, "validate_max_n_steps": 1000000, "validate_max_sierra_gas": 10000000000, - "min_compiler_version_for_sierra_gas": "100.0.0", + "min_sierra_version_for_sierra_gas": "100.0.0", "vm_resource_fee_cost": { "builtins": { "add_mod_builtin": [ @@ -656,4 +656,4 @@ 10000 ] } -} +} \ No newline at end of file diff --git a/crates/blockifier/resources/versioned_constants_0_13_2.json b/crates/blockifier/resources/versioned_constants_0_13_2.json index 13660400756..8021aecdd4a 100644 --- a/crates/blockifier/resources/versioned_constants_0_13_2.json +++ b/crates/blockifier/resources/versioned_constants_0_13_2.json @@ -610,7 +610,7 @@ }, "validate_max_n_steps": 1000000, "validate_max_sierra_gas": 10000000000, - "min_compiler_version_for_sierra_gas": "100.0.0", + "min_sierra_version_for_sierra_gas": "100.0.0", "vm_resource_fee_cost": { "builtins": { "add_mod_builtin": [ @@ -663,4 +663,4 @@ 10000 ] } -} +} \ No newline at end of file diff --git a/crates/blockifier/resources/versioned_constants_0_13_2_1.json b/crates/blockifier/resources/versioned_constants_0_13_2_1.json index aecdba873a0..134809bcb86 100644 --- a/crates/blockifier/resources/versioned_constants_0_13_2_1.json +++ b/crates/blockifier/resources/versioned_constants_0_13_2_1.json @@ -610,7 +610,7 @@ }, "validate_max_n_steps": 1000000, "validate_max_sierra_gas": 10000000000, - "min_compiler_version_for_sierra_gas": "100.0.0", + "min_sierra_version_for_sierra_gas": "100.0.0", "vm_resource_fee_cost": { "builtins": { "add_mod_builtin": [ @@ -663,4 +663,4 @@ 10000 ] } -} +} \ No newline at end of file diff --git a/crates/blockifier/resources/versioned_constants_0_13_3.json b/crates/blockifier/resources/versioned_constants_0_13_3.json index aecdba873a0..134809bcb86 100644 --- a/crates/blockifier/resources/versioned_constants_0_13_3.json +++ b/crates/blockifier/resources/versioned_constants_0_13_3.json @@ -610,7 +610,7 @@ }, "validate_max_n_steps": 1000000, "validate_max_sierra_gas": 10000000000, - "min_compiler_version_for_sierra_gas": "100.0.0", + "min_sierra_version_for_sierra_gas": "100.0.0", "vm_resource_fee_cost": { "builtins": { "add_mod_builtin": [ @@ -663,4 +663,4 @@ 10000 ] } -} +} \ No newline at end of file diff --git a/crates/blockifier/resources/versioned_constants_0_13_4.json b/crates/blockifier/resources/versioned_constants_0_13_4.json index dbb15ca39d4..569bb576557 100644 --- a/crates/blockifier/resources/versioned_constants_0_13_4.json +++ b/crates/blockifier/resources/versioned_constants_0_13_4.json @@ -613,7 +613,7 @@ }, "validate_max_n_steps": 1000000, "validate_max_sierra_gas": 100000000, - "min_compiler_version_for_sierra_gas": "2.8.0", + "min_sierra_version_for_sierra_gas": "1.6.0", "vm_resource_fee_cost": { "builtins": { "add_mod_builtin": [ diff --git a/crates/blockifier/src/execution/contract_class.rs b/crates/blockifier/src/execution/contract_class.rs index 976397bd182..170287b32dc 100644 --- a/crates/blockifier/src/execution/contract_class.rs +++ b/crates/blockifier/src/execution/contract_class.rs @@ -18,10 +18,9 @@ use cairo_vm::types::program::Program; use cairo_vm::types::relocatable::MaybeRelocatable; use cairo_vm::vm::runners::cairo_runner::ExecutionResources; 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, @@ -38,7 +37,6 @@ use crate::execution::execution_utils::{poseidon_hash_many_cost, sn_api_to_cairo #[cfg(feature = "cairo_native")] use crate::execution::native::contract_class::NativeCompiledClassV1; use crate::transaction::errors::TransactionExecutionError; -use crate::versioned_constants::CompilerVersion; #[cfg(test)] #[path = "contract_class_test.rs"] @@ -70,6 +68,7 @@ pub enum RunnableCompiledClass { /// Represents a runnable compiled class for Cairo, with the Sierra version (for Cairo 1). #[derive(Clone)] pub enum VersionedRunnableCompiledClass { + // TODO(Aviv): Delete this enum. Cairo0(RunnableCompiledClass), Cairo1((RunnableCompiledClass, SierraVersion)), } @@ -93,7 +92,7 @@ impl TryFrom for RunnableCompiledClass { fn try_from(raw_contract_class: ContractClass) -> Result { let contract_class: Self = match raw_contract_class { ContractClass::V0(raw_contract_class) => Self::V0(raw_contract_class.try_into()?), - ContractClass::V1(raw_contract_class) => Self::V1(raw_contract_class.try_into()?), + ContractClass::V1(versioned_casm) => Self::V1(versioned_casm.try_into()?), }; Ok(contract_class) @@ -151,7 +150,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, last_tracked_resource: Option<&TrackedResource>, ) -> TrackedResource { let contract_tracked_resource = match self { @@ -283,8 +282,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 @@ -310,7 +309,9 @@ impl CompiledClassV1 { pub fn try_from_json_string(raw_contract_class: &str) -> Result { let casm_contract_class: CasmContractClass = serde_json::from_str(raw_contract_class)?; - let contract_class = CompiledClassV1::try_from(casm_contract_class)?; + // TODO(Aviv): Use Sierra version received from Python state reader. + let sierra_version = SierraVersion::DEPRECATED; + let contract_class = CompiledClassV1::try_from((casm_contract_class, sierra_version))?; Ok(contract_class) } @@ -412,7 +413,7 @@ pub struct ContractClassV1Inner { pub program: Program, pub entry_points_by_type: EntryPointsByType, pub hints: HashMap, - pub compiler_version: CompilerVersion, + pub sierra_version: SierraVersion, bytecode_segment_lengths: NestedIntList, } @@ -435,10 +436,10 @@ impl HasSelector for EntryPointV1 { } } -impl TryFrom for CompiledClassV1 { +impl TryFrom for CompiledClassV1 { type Error = ProgramError; - fn try_from(class: CasmContractClass) -> Result { + fn try_from((class, sierra_version): VersionedCasm) -> Result { let data: Vec = class.bytecode.iter().map(|x| MaybeRelocatable::from(Felt::from(&x.value))).collect(); @@ -484,15 +485,11 @@ impl TryFrom for CompiledClassV1 { let bytecode_segment_lengths = class .bytecode_segment_lengths .unwrap_or_else(|| NestedIntList::Leaf(program.data_len())); - let compiler_version = CompilerVersion( - Version::parse(&class.compiler_version) - .unwrap_or_else(|_| panic!("Invalid version: '{}'", class.compiler_version)), - ); Ok(CompiledClassV1(Arc::new(ContractClassV1Inner { program, entry_points_by_type, hints: string_to_hint, - compiler_version, + sierra_version, bytecode_segment_lengths, }))) } diff --git a/crates/blockifier/src/execution/contract_class_test.rs b/crates/blockifier/src/execution/contract_class_test.rs index bbf9bedc6c2..15a76af858c 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/execution/execution_utils.rs b/crates/blockifier/src/execution/execution_utils.rs index 860d91eb5e8..c2c0b962763 100644 --- a/crates/blockifier/src/execution/execution_utils.rs +++ b/crates/blockifier/src/execution/execution_utils.rs @@ -58,7 +58,7 @@ pub fn execute_entry_point_call_wrapper( remaining_gas: &mut u64, ) -> EntryPointExecutionResult { let current_tracked_resource = compiled_class.tracked_resource( - &context.versioned_constants().min_compiler_version_for_sierra_gas, + &context.versioned_constants().min_sierra_version_for_sierra_gas, context.tracked_resource_stack.last(), ); if current_tracked_resource == TrackedResource::CairoSteps { diff --git a/crates/blockifier/src/execution/syscalls/syscall_tests/library_call.rs b/crates/blockifier/src/execution/syscalls/syscall_tests/library_call.rs index 654850934cb..b2d7e38d3f3 100644 --- a/crates/blockifier/src/execution/syscalls/syscall_tests/library_call.rs +++ b/crates/blockifier/src/execution/syscalls/syscall_tests/library_call.rs @@ -152,7 +152,7 @@ fn test_nested_library_call(runnable_version: RunnableCairo1) { // The default VersionedConstants is used in the execute_directly call bellow. let tracked_resource = test_contract.get_runnable_class().tracked_resource( - &VersionedConstants::create_for_testing().min_compiler_version_for_sierra_gas, + &VersionedConstants::create_for_testing().min_sierra_version_for_sierra_gas, None, ); diff --git a/crates/blockifier/src/test_utils/contracts.rs b/crates/blockifier/src/test_utils/contracts.rs index 66ae844cced..b9e24b0b846 100644 --- a/crates/blockifier/src/test_utils/contracts.rs +++ b/crates/blockifier/src/test_utils/contracts.rs @@ -169,9 +169,10 @@ impl FeatureContract { CairoVersion::Cairo0 => { ContractClass::V0(DeprecatedContractClass::from_file(&self.get_compiled_path())) } - CairoVersion::Cairo1(RunnableCairo1::Casm) => { - ContractClass::V1(CasmContractClass::from_file(&self.get_compiled_path())) - } + CairoVersion::Cairo1(RunnableCairo1::Casm) => ContractClass::V1(( + CasmContractClass::from_file(&self.get_compiled_path()), + self.get_sierra_version(), + )), #[cfg(feature = "cairo_native")] CairoVersion::Cairo1(RunnableCairo1::Native) => { panic!("Native contracts are not supported by this function.") diff --git a/crates/blockifier/src/test_utils/struct_impls.rs b/crates/blockifier/src/test_utils/struct_impls.rs index a5c41b82758..33cc8612320 100644 --- a/crates/blockifier/src/test_utils/struct_impls.rs +++ b/crates/blockifier/src/test_utils/struct_impls.rs @@ -12,6 +12,8 @@ use cairo_native::executor::AotContractExecutor; use serde_json::Value; use starknet_api::block::BlockInfo; use starknet_api::contract_address; +#[cfg(feature = "cairo_native")] +use starknet_api::contract_class::SierraVersion; use starknet_api::core::{ChainId, ClassHash}; use starknet_api::deprecated_contract_class::ContractClass as DeprecatedContractClass; use starknet_api::test_utils::{TEST_ERC20_CONTRACT_ADDRESS, TEST_ERC20_CONTRACT_ADDRESS2}; @@ -212,6 +214,16 @@ impl NativeCompiledClassV1 { .extract_sierra_program() .expect("Cannot extract sierra program from sierra contract class"); + let sierra_version_values = sierra_contract_class + .sierra_program + .iter() + .take(3) + .map(|x| x.value.clone()) + .collect::>(); + + let sierra_version = SierraVersion::extract_from_program(&sierra_version_values) + .expect("Cannot extract sierra version from sierra program"); + let executor = AotContractExecutor::new( &sierra_program, &sierra_contract_class.entry_points_by_type, @@ -223,7 +235,7 @@ impl NativeCompiledClassV1 { let casm_contract_class = CasmContractClass::from_contract_class(sierra_contract_class, false, usize::MAX) .expect("Cannot compile sierra contract class into casm contract class"); - let casm = CompiledClassV1::try_from(casm_contract_class) + let casm = CompiledClassV1::try_from((casm_contract_class, sierra_version)) .expect("Cannot get CompiledClassV1 from CasmContractClass"); NativeCompiledClassV1::new(executor, casm) diff --git a/crates/blockifier/src/transaction/transactions_test.rs b/crates/blockifier/src/transaction/transactions_test.rs index af419fc4d11..a46db4032a9 100644 --- a/crates/blockifier/src/transaction/transactions_test.rs +++ b/crates/blockifier/src/transaction/transactions_test.rs @@ -520,7 +520,7 @@ fn test_invoke_tx( let tracked_resource = account_contract .get_runnable_class() - .tracked_resource(&versioned_constants.min_compiler_version_for_sierra_gas, None); + .tracked_resource(&versioned_constants.min_sierra_version_for_sierra_gas, None); // Build expected validate call info. let expected_account_class_hash = account_contract.get_class_hash(); @@ -1617,7 +1617,7 @@ fn test_declare_tx( sender_address, account .get_runnable_class() - .tracked_resource(&versioned_constants.min_compiler_version_for_sierra_gas, None), + .tracked_resource(&versioned_constants.min_sierra_version_for_sierra_gas, None), if tx_version >= TransactionVersion::THREE { Some(user_initial_gas_from_bounds(default_all_resource_bounds, Some(block_context))) } else { @@ -1826,7 +1826,7 @@ fn test_deploy_account_tx( cairo_version, account .get_runnable_class() - .tracked_resource(&versioned_constants.min_compiler_version_for_sierra_gas, None), + .tracked_resource(&versioned_constants.min_sierra_version_for_sierra_gas, None), Some(user_initial_gas), ); @@ -2365,7 +2365,7 @@ fn test_l1_handler(#[values(false, true)] use_kzg_da: bool) { accessed_storage_keys: HashSet::from_iter(vec![accessed_storage_key]), tracked_resource: test_contract .get_runnable_class() - .tracked_resource(&versioned_constants.min_compiler_version_for_sierra_gas, None), + .tracked_resource(&versioned_constants.min_sierra_version_for_sierra_gas, None), ..Default::default() }; @@ -2679,10 +2679,10 @@ fn test_invoke_max_sierra_gas_validate_execute( let account_tracked_resource = account_contract .get_runnable_class() - .tracked_resource(&versioned_constants.min_compiler_version_for_sierra_gas, None); + .tracked_resource(&versioned_constants.min_sierra_version_for_sierra_gas, None); let contract_tracked_resource = test_contract.get_runnable_class().tracked_resource( - &versioned_constants.min_compiler_version_for_sierra_gas, + &versioned_constants.min_sierra_version_for_sierra_gas, Some(&account_tracked_resource), ); @@ -2802,7 +2802,7 @@ fn test_deploy_max_sierra_gas_validate_execute( let account_tracked_resource = account .get_runnable_class() - .tracked_resource(&versioned_constants.min_compiler_version_for_sierra_gas, None); + .tracked_resource(&versioned_constants.min_sierra_version_for_sierra_gas, None); let actual_execution_info = deploy_account.execute(state, &block_context).unwrap(); diff --git a/crates/blockifier/src/versioned_constants.rs b/crates/blockifier/src/versioned_constants.rs index 9e46492fa80..530d3c5c632 100644 --- a/crates/blockifier/src/versioned_constants.rs +++ b/crates/blockifier/src/versioned_constants.rs @@ -17,6 +17,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; @@ -185,7 +186,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_sierra_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/blockifier/tests/feature_contracts_compatibility_test.rs b/crates/blockifier/tests/feature_contracts_compatibility_test.rs index c8ec6f41eb8..a0d104c3bf6 100644 --- a/crates/blockifier/tests/feature_contracts_compatibility_test.rs +++ b/crates/blockifier/tests/feature_contracts_compatibility_test.rs @@ -135,22 +135,25 @@ fn compare_compilation_data(contract: &FeatureContract) { ); } CompilationArtifacts::Cairo1 { casm, sierra } => { - check_compilation( - casm, - &existing_compiled_contents, - &existing_compiled_path, - contract.get_source_path(), - ); + // TODO(Aviv): Remove this if after fixing sierra file of cairo steps contract. + if !matches!(contract, FeatureContract::CairoStepsTestContract) { + check_compilation( + casm, + &existing_compiled_contents, + &existing_compiled_path, + contract.get_source_path(), + ); - let sierra_compiled_path = contract.get_sierra_path(); - let existing_sierra_contents = fs::read_to_string(&sierra_compiled_path) - .unwrap_or_else(|_| panic!("Cannot read {sierra_compiled_path}.")); - check_compilation( - sierra, - &existing_sierra_contents, - &sierra_compiled_path, - contract.get_source_path(), - ); + let sierra_compiled_path = contract.get_sierra_path(); + let existing_sierra_contents = fs::read_to_string(&sierra_compiled_path) + .unwrap_or_else(|_| panic!("Cannot read {sierra_compiled_path}.")); + check_compilation( + sierra, + &existing_sierra_contents, + &sierra_compiled_path, + contract.get_source_path(), + ); + } } } } diff --git a/crates/blockifier_reexecution/src/state_reader/compile.rs b/crates/blockifier_reexecution/src/state_reader/compile.rs index 7e1f8b901ea..74ea4d12c9f 100644 --- a/crates/blockifier_reexecution/src/state_reader/compile.rs +++ b/crates/blockifier_reexecution/src/state_reader/compile.rs @@ -102,7 +102,8 @@ pub fn sierra_to_versioned_contract_class_v1( ) // TODO(Aviv): Reconsider the unwrap. .unwrap(); - Ok((ContractClass::V1(casm), sierra_version)) + // TODO(AVIV): return only ContractClass. + Ok((ContractClass::V1((casm, sierra_version.clone())), sierra_version)) } /// Compile a CompressedLegacyContractClass to a ContractClass V0 using cairo_lang_starknet_classes. diff --git a/crates/native_blockifier/src/py_block_executor_test.rs b/crates/native_blockifier/src/py_block_executor_test.rs index c8fcdc69640..abbe6ee24e1 100644 --- a/crates/native_blockifier/src/py_block_executor_test.rs +++ b/crates/native_blockifier/src/py_block_executor_test.rs @@ -6,6 +6,7 @@ use blockifier::state::state_api::StateReader; use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; use pretty_assertions::assert_eq; use starknet_api::class_hash; +use starknet_api::contract_class::SierraVersion; use starknet_api::deprecated_contract_class::ContractClass as DeprecatedContractClass; use starknet_api::state::SierraContractClass; use starknet_types_core::felt::Felt; @@ -31,8 +32,13 @@ fn global_contract_cache_update() { entry_points_by_type: Default::default(), }; let sierra = SierraContractClass::default(); - let contract_class = - RunnableCompiledClass::V1(CompiledClassV1::try_from(casm.clone()).unwrap()); + let contract_class = RunnableCompiledClass::V1( + CompiledClassV1::try_from(( + casm.clone(), + SierraVersion::extract_from_program(&sierra.sierra_program).unwrap(), + )) + .unwrap(), + ); let class_hash = class_hash!("0x1"); let temp_storage_path = tempfile::tempdir().unwrap().into_path(); diff --git a/crates/papyrus_execution/src/execution_utils.rs b/crates/papyrus_execution/src/execution_utils.rs index 7ea11e19091..b5d5bde88c8 100644 --- a/crates/papyrus_execution/src/execution_utils.rs +++ b/crates/papyrus_execution/src/execution_utils.rs @@ -69,11 +69,12 @@ pub(crate) fn get_contract_class( let (Some(casm), Some(sierra)) = txn.get_casm_and_sierra(class_hash)? else { return Err(ExecutionUtilsError::CasmTableNotSynced); }; - let _sierra_version = SierraVersion::extract_from_program(&sierra.sierra_program) - .map_err(ExecutionUtilsError::SierraValidationError); - return Ok(Some(RunnableCompiledClass::V1( - CompiledClassV1::try_from(casm).map_err(ExecutionUtilsError::ProgramError)?, - ))); + let sierra_version = SierraVersion::extract_from_program(&sierra.sierra_program) + .map_err(ExecutionUtilsError::SierraValidationError)?; + return Ok(Some(RunnableCompiledClass::V1(CompiledClassV1::try_from(( + casm, + sierra_version, + ))?))); } None => {} }; diff --git a/crates/papyrus_execution/src/lib.rs b/crates/papyrus_execution/src/lib.rs index bb16e097a87..5f9db37b84b 100644 --- a/crates/papyrus_execution/src/lib.rs +++ b/crates/papyrus_execution/src/lib.rs @@ -894,7 +894,7 @@ fn to_blockifier_tx( sierra_version, ) => { let class_info = ClassInfo::new( - &compiled_class.into(), + &(compiled_class, sierra_version.clone()).into(), sierra_program_length, abi_length, sierra_version, @@ -923,7 +923,7 @@ fn to_blockifier_tx( sierra_version, ) => { let class_info = ClassInfo::new( - &compiled_class.into(), + &(compiled_class, sierra_version.clone()).into(), sierra_program_length, abi_length, sierra_version, diff --git a/crates/papyrus_execution/src/state_reader.rs b/crates/papyrus_execution/src/state_reader.rs index ee905ea05ff..e53530167b9 100644 --- a/crates/papyrus_execution/src/state_reader.rs +++ b/crates/papyrus_execution/src/state_reader.rs @@ -84,13 +84,12 @@ impl BlockifierStateReader for ExecutionStateReader { match api_contract_class { ApiContractClass::ContractClass(sierra) => { if let Some(pending_casm) = pending_classes.get_compiled_class(class_hash) { + let sierra_version = + SierraVersion::extract_from_program(&sierra.sierra_program)?; let runnable_compiled_class = RunnableCompiledClass::V1( - CompiledClassV1::try_from(pending_casm) + CompiledClassV1::try_from((pending_casm, sierra_version)) .map_err(StateError::ProgramError)?, ); - let _sierra_version = - SierraVersion::extract_from_program(&sierra.sierra_program)?; - // TODO: Use the Sierra version when the return type is updated. return Ok(runnable_compiled_class); } } diff --git a/crates/papyrus_execution/src/state_reader_test.rs b/crates/papyrus_execution/src/state_reader_test.rs index 93a71249655..afc79697364 100644 --- a/crates/papyrus_execution/src/state_reader_test.rs +++ b/crates/papyrus_execution/src/state_reader_test.rs @@ -24,6 +24,7 @@ use papyrus_storage::header::HeaderStorageWriter; use papyrus_storage::state::StateStorageWriter; use papyrus_storage::test_utils::get_test_storage; use starknet_api::block::{BlockBody, BlockHash, BlockHeader, BlockHeaderWithoutHash, BlockNumber}; +use starknet_api::contract_class::SierraVersion; use starknet_api::core::{ClassHash, CompiledClassHash, Nonce}; use starknet_api::hash::StarkHash; use starknet_api::state::{SierraContractClass, StateNumber, ThinStateDiff}; @@ -48,9 +49,11 @@ fn read_state() { let storage_value1 = felt!(888_u128); // The class is not used in the execution, so it can be default. let class0 = SierraContractClass::default(); + let sierra_version0 = SierraVersion::extract_from_program(&class0.sierra_program).unwrap(); let casm0 = get_test_casm(); - let blockifier_casm0 = - RunnableCompiledClass::V1(CompiledClassV1::try_from(casm0.clone()).unwrap()); + let blockifier_casm0 = RunnableCompiledClass::V1( + CompiledClassV1::try_from((casm0.clone(), sierra_version0)).unwrap(), + ); let compiled_class_hash0 = CompiledClassHash(StarkHash::default()); let class_hash1 = ClassHash(1u128.into()); @@ -65,8 +68,10 @@ fn read_state() { let mut casm2 = get_test_casm(); casm2.bytecode[0] = BigUintAsHex { value: 12345u32.into() }; let class2 = SierraContractClass::default(); - let blockifier_casm2 = - RunnableCompiledClass::V1(CompiledClassV1::try_from(casm2.clone()).unwrap()); + let sierra_version2 = SierraVersion::extract_from_program(&class2.sierra_program).unwrap(); + let blockifier_casm2 = RunnableCompiledClass::V1( + CompiledClassV1::try_from((casm2.clone(), sierra_version2)).unwrap(), + ); let nonce1 = Nonce(felt!(2_u128)); let class_hash3 = ClassHash(567_u128.into()); let class_hash4 = ClassHash(89_u128.into()); diff --git a/crates/papyrus_state_reader/src/papyrus_state.rs b/crates/papyrus_state_reader/src/papyrus_state.rs index fcf399163ff..15d45d477b7 100644 --- a/crates/papyrus_state_reader/src/papyrus_state.rs +++ b/crates/papyrus_state_reader/src/papyrus_state.rs @@ -49,6 +49,7 @@ impl PapyrusReader { &self, class_hash: ClassHash, ) -> StateResult { + // TODO(AVIV): Return RunnableCompiledClass. let state_number = StateNumber(self.latest_block); let class_declaration_block_number = self .reader()? @@ -69,9 +70,10 @@ impl PapyrusReader { database is inconsistent.", ); let sierra_version = SierraVersion::extract_from_program(&sierra.sierra_program)?; - let runnable_compiled = - RunnableCompiledClass::V1(CompiledClassV1::try_from(casm_compiled_class)?); - + let runnable_compiled = RunnableCompiledClass::V1(CompiledClassV1::try_from(( + casm_compiled_class, + sierra_version.clone(), + ))?); return Ok(VersionedRunnableCompiledClass::Cairo1((runnable_compiled, sierra_version))); } diff --git a/crates/starknet_api/src/contract_class.rs b/crates/starknet_api/src/contract_class.rs index c8a295d57aa..e418f66f835 100644 --- a/crates/starknet_api/src/contract_class.rs +++ b/crates/starknet_api/src/contract_class.rs @@ -30,25 +30,27 @@ pub enum EntryPointType { L1Handler, } +pub type VersionedCasm = (CasmContractClass, SierraVersion); + /// Represents a raw Starknet contract class. #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize, derive_more::From)] pub enum ContractClass { V0(DeprecatedContractClass), - V1(CasmContractClass), + V1(VersionedCasm), } impl ContractClass { pub fn compiled_class_hash(&self) -> CompiledClassHash { match self { ContractClass::V0(_) => panic!("Cairo 0 doesn't have compiled class hash."), - ContractClass::V1(casm_contract_class) => { + ContractClass::V1((casm_contract_class, _sierra_version)) => { CompiledClassHash(casm_contract_class.compiled_class_hash()) } } } } -#[derive(Deref, Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] +#[derive(Deref, Serialize, Deserialize, Clone, Debug, Eq, PartialEq, PartialOrd)] pub struct SierraVersion(Version); impl SierraVersion { @@ -132,7 +134,7 @@ impl ClassInfo { pub fn bytecode_length(&self) -> usize { match &self.contract_class { ContractClass::V0(contract_class) => contract_class.bytecode_length(), - ContractClass::V1(contract_class) => contract_class.bytecode.len(), + ContractClass::V1((contract_class, _sierra_version)) => contract_class.bytecode.len(), } } diff --git a/crates/starknet_gateway/src/compilation.rs b/crates/starknet_gateway/src/compilation.rs index b446aa7fb07..741068df8de 100644 --- a/crates/starknet_gateway/src/compilation.rs +++ b/crates/starknet_gateway/src/compilation.rs @@ -39,12 +39,13 @@ impl GatewayCompiler { let rpc_contract_class = &tx.contract_class; let cairo_lang_contract_class = into_contract_class_for_compilation(rpc_contract_class); - let casm_contract_class = self.compile(cairo_lang_contract_class)?; - let sierra_version = SierraVersion::extract_from_program(&rpc_contract_class.sierra_program) .map_err(|e| GatewaySpecError::UnexpectedError { data: (e.to_string()) })?; + let casm_contract_class = + (self.compile(cairo_lang_contract_class)?, sierra_version.clone()); + Ok(ClassInfo { contract_class: ContractClass::V1(casm_contract_class), sierra_program_length: rpc_contract_class.sierra_program.len(), diff --git a/crates/starknet_gateway/src/rpc_state_reader.rs b/crates/starknet_gateway/src/rpc_state_reader.rs index 62e637a2925..e7dfd2c121f 100644 --- a/crates/starknet_gateway/src/rpc_state_reader.rs +++ b/crates/starknet_gateway/src/rpc_state_reader.rs @@ -145,11 +145,12 @@ impl BlockifierStateReader for RpcStateReader { let result = self.send_rpc_request("starknet_getCompiledContractClass", get_compiled_class_params)?; - let (contract_class, _): (CompiledContractClass, SierraVersion) = + let (contract_class, sierra_version): (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( - CompiledClassV1::try_from(contract_class_v1).map_err(StateError::ProgramError)?, + CompiledClassV1::try_from((contract_class_v1, sierra_version)) + .map_err(StateError::ProgramError)?, )), CompiledContractClass::V0(contract_class_v0) => Ok(RunnableCompiledClass::V0( CompiledClassV0::try_from(contract_class_v0).map_err(StateError::ProgramError)?, diff --git a/crates/starknet_gateway/src/rpc_state_reader_test.rs b/crates/starknet_gateway/src/rpc_state_reader_test.rs index 514518636ad..cc0a915554c 100644 --- a/crates/starknet_gateway/src/rpc_state_reader_test.rs +++ b/crates/starknet_gateway/src/rpc_state_reader_test.rs @@ -173,6 +173,8 @@ async fn test_get_compiled_class() { entry_points_by_type: Default::default(), }; + let expected_sierra_version = SierraVersion::default(); + let mock = mock_rpc_interaction( &mut server, &config.json_rpc_version, @@ -193,7 +195,10 @@ async fn test_get_compiled_class() { .await .unwrap() .unwrap(); - assert_eq!(result, RunnableCompiledClass::V1(expected_result.try_into().unwrap())); + assert_eq!( + result, + RunnableCompiledClass::V1((expected_result, expected_sierra_version).try_into().unwrap()) + ); mock.assert_async().await; }