diff --git a/crates/starknet_api/src/contract_class.rs b/crates/starknet_api/src/contract_class.rs index e633e3e4ae..9c0f02aebf 100644 --- a/crates/starknet_api/src/contract_class.rs +++ b/crates/starknet_api/src/contract_class.rs @@ -3,6 +3,10 @@ use serde::{Deserialize, Serialize}; use crate::core::CompiledClassHash; use crate::deprecated_contract_class::ContractClass as DeprecatedContractClass; +use crate::StarknetApiError; + +// Calldata. +pub const WORD_WIDTH: usize = 32; #[derive( Debug, Default, Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord, @@ -41,9 +45,58 @@ impl ContractClass { /// 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)] +// TODO(Ayelet,10/02/2024): Change to bytes. pub struct ClassInfo { // TODO(Noa): Consider using Arc. pub contract_class: ContractClass, pub sierra_program_length: usize, pub abi_length: usize, } + +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(), + } + } + + pub fn contract_class(&self) -> ContractClass { + self.contract_class.clone() + } + + pub fn sierra_program_length(&self) -> usize { + self.sierra_program_length + } + + pub fn abi_length(&self) -> usize { + self.abi_length + } + + pub fn code_size(&self) -> usize { + (self.bytecode_length() + self.sierra_program_length()) + // We assume each felt is a word. + * WORD_WIDTH + + self.abi_length() + } + + pub fn new( + contract_class: &ContractClass, + sierra_program_length: usize, + abi_length: usize, + ) -> Result { + let (contract_class_version, condition) = match contract_class { + ContractClass::V0(_) => (0, sierra_program_length == 0), + ContractClass::V1(_) => (1, sierra_program_length > 0), + }; + + if condition { + Ok(Self { contract_class: contract_class.clone(), sierra_program_length, abi_length }) + } else { + Err(StarknetApiError::ContractClassVersionSierraProgramLengthMismatch { + contract_class_version, + sierra_program_length, + }) + } + } +} diff --git a/crates/starknet_api/src/lib.rs b/crates/starknet_api/src/lib.rs index 98f9f42eda..4ba0366232 100644 --- a/crates/starknet_api/src/lib.rs +++ b/crates/starknet_api/src/lib.rs @@ -49,6 +49,14 @@ pub enum StarknetApiError { InvalidStarknetVersion(Vec), #[error("NonzeroGasPrice cannot be zero.")] ZeroGasPrice, + #[error( + "Sierra program length must be > 0 for Cairo1, and == 0 for Cairo0. Got: \ + {sierra_program_length:?} for contract class version {contract_class_version:?}" + )] + ContractClassVersionSierraProgramLengthMismatch { + contract_class_version: u8, + sierra_program_length: usize, + }, } pub type StarknetApiResult = Result;