From c56e01a72a57c6e81fb1cda163bd8eb026d2e137 Mon Sep 17 00:00:00 2001 From: Aviv Greenburg Date: Wed, 30 Oct 2024 18:46:54 +0200 Subject: [PATCH] chore(blockifier): implement staknet_api class_info to match blockifier class_info --- crates/blockifier/src/test_utils/declare.rs | 3 +- .../src/test_utils/deploy_account.rs | 1 + crates/blockifier/src/test_utils/invoke.rs | 1 + crates/starknet_api/src/contract_class.rs | 53 +++++++++++++++++++ crates/starknet_api/src/lib.rs | 8 +++ 5 files changed, 65 insertions(+), 1 deletion(-) diff --git a/crates/blockifier/src/test_utils/declare.rs b/crates/blockifier/src/test_utils/declare.rs index d78f3ff06c..cfafb583ef 100644 --- a/crates/blockifier/src/test_utils/declare.rs +++ b/crates/blockifier/src/test_utils/declare.rs @@ -7,6 +7,7 @@ use crate::transaction::transactions::DeclareTransaction; pub fn declare_tx(declare_tx_args: DeclareTxArgs, class_info: ClassInfo) -> AccountTransaction { let tx_hash = declare_tx_args.tx_hash; let declare_tx = starknet_api::test_utils::declare::declare_tx(declare_tx_args); + let executable_declare = DeclareTransaction::new(declare_tx, tx_hash, class_info).unwrap(); - AccountTransaction::Declare(DeclareTransaction::new(declare_tx, tx_hash, class_info).unwrap()) + AccountTransaction::Declare(executable_declare) } diff --git a/crates/blockifier/src/test_utils/deploy_account.rs b/crates/blockifier/src/test_utils/deploy_account.rs index b48ae6a320..24397f650a 100644 --- a/crates/blockifier/src/test_utils/deploy_account.rs +++ b/crates/blockifier/src/test_utils/deploy_account.rs @@ -24,5 +24,6 @@ pub fn deploy_account_tx( ); let executable_deploy_account_tx = DeployAccountTransaction::new(deploy_account_tx, tx_hash, contract_address); + AccountTransaction::DeployAccount(executable_deploy_account_tx) } diff --git a/crates/blockifier/src/test_utils/invoke.rs b/crates/blockifier/src/test_utils/invoke.rs index d4fff4923b..b906283178 100644 --- a/crates/blockifier/src/test_utils/invoke.rs +++ b/crates/blockifier/src/test_utils/invoke.rs @@ -27,5 +27,6 @@ pub fn invoke_tx(invoke_args: InvokeTxArgs) -> AccountTransaction { true => InvokeTransaction::new_for_query(invoke_tx, tx_hash), false => InvokeTransaction::new(invoke_tx, tx_hash), }; + AccountTransaction::Invoke(invoke_tx) } 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;