Skip to content

Commit

Permalink
refactor(blockifier): min compiler version for sierra gas type
Browse files Browse the repository at this point in the history
  • Loading branch information
AvivYossef-starkware committed Dec 18, 2024
1 parent 01f3e55 commit 1683c47
Show file tree
Hide file tree
Showing 16 changed files with 81 additions and 49 deletions.
27 changes: 11 additions & 16 deletions crates/blockifier/src/execution/contract_class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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"]
Expand Down Expand Up @@ -93,7 +91,7 @@ impl TryFrom<ContractClass> for RunnableCompiledClass {
fn try_from(raw_contract_class: ContractClass) -> Result<Self, Self::Error> {
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)
Expand Down Expand Up @@ -151,7 +149,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 {
Expand Down Expand Up @@ -283,8 +281,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
Expand All @@ -310,7 +308,8 @@ impl CompiledClassV1 {

pub fn try_from_json_string(raw_contract_class: &str) -> Result<CompiledClassV1, ProgramError> {
let casm_contract_class: CasmContractClass = serde_json::from_str(raw_contract_class)?;
let contract_class = CompiledClassV1::try_from(casm_contract_class)?;
let sierra_version = SierraVersion::default();
let contract_class = CompiledClassV1::try_from((casm_contract_class, sierra_version))?;

Ok(contract_class)
}
Expand Down Expand Up @@ -412,7 +411,7 @@ pub struct ContractClassV1Inner {
pub program: Program,
pub entry_points_by_type: EntryPointsByType<EntryPointV1>,
pub hints: HashMap<String, Hint>,
pub compiler_version: CompilerVersion,
pub sierra_version: SierraVersion,
bytecode_segment_lengths: NestedIntList,
}

Expand All @@ -435,10 +434,10 @@ impl HasSelector for EntryPointV1 {
}
}

impl TryFrom<CasmContractClass> for CompiledClassV1 {
impl TryFrom<VersionedCasm> for CompiledClassV1 {
type Error = ProgramError;

fn try_from(class: CasmContractClass) -> Result<Self, Self::Error> {
fn try_from((class, sierra_version): VersionedCasm) -> Result<Self, Self::Error> {
let data: Vec<MaybeRelocatable> =
class.bytecode.iter().map(|x| MaybeRelocatable::from(Felt::from(&x.value))).collect();

Expand Down Expand Up @@ -484,15 +483,11 @@ impl TryFrom<CasmContractClass> 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,
})))
}
Expand Down
2 changes: 1 addition & 1 deletion crates/blockifier/src/execution/contract_class_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
7 changes: 4 additions & 3 deletions crates/blockifier/src/test_utils/contracts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.")
Expand Down
13 changes: 12 additions & 1 deletion crates/blockifier/src/test_utils/struct_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use cairo_native::executor::AotContractExecutor;
use serde_json::Value;
use starknet_api::block::{BlockInfo, BlockNumber, BlockTimestamp, NonzeroGasPrice};
use starknet_api::contract_address;
use starknet_api::contract_class::SierraVersion;
use starknet_api::core::{ChainId, ClassHash};
use starknet_api::deprecated_contract_class::ContractClass as DeprecatedContractClass;

Expand Down Expand Up @@ -262,6 +263,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::<Vec<_>>();

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,
Expand All @@ -273,7 +284,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)
Expand Down
3 changes: 2 additions & 1 deletion crates/blockifier/src/versioned_constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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_compiler_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.
Expand Down
2 changes: 1 addition & 1 deletion crates/blockifier_reexecution/src/state_reader/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ pub fn sierra_to_versioned_contract_class_v1(
)
// TODO(Aviv): Reconsider the unwrap.
.unwrap();
Ok((ContractClass::V1(casm), sierra_version))
Ok((ContractClass::V1((casm, sierra_version.clone())), sierra_version))
}

/// Compile a CompressedLegacyContractClass to a ContractClass V0 using cairo_lang_starknet_classes.
Expand Down
10 changes: 8 additions & 2 deletions crates/native_blockifier/src/py_block_executor_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use cached::Cached;
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;
Expand All @@ -32,8 +33,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();
Expand Down
5 changes: 3 additions & 2 deletions crates/papyrus_execution/src/execution_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,11 @@ pub(crate) fn get_versioned_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)?;
let runnable_compiled_class = RunnableCompiledClass::V1(
CompiledClassV1::try_from(casm).map_err(ExecutionUtilsError::ProgramError)?,
CompiledClassV1::try_from((casm, sierra_version.clone()))
.map_err(ExecutionUtilsError::ProgramError)?,
);
let sierra_version = SierraVersion::extract_from_program(&sierra.sierra_program)?;
return Ok(Some(VersionedRunnableCompiledClass::Cairo1((
runnable_compiled_class,
sierra_version,
Expand Down
4 changes: 2 additions & 2 deletions crates/papyrus_execution/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
8 changes: 5 additions & 3 deletions crates/papyrus_execution/src/state_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,12 @@ impl BlockifierStateReader for ExecutionStateReader {
.and_then(|pending_data| pending_data.classes.get_class(class_hash))
{
let runnable_compiled_class = RunnableCompiledClass::V1(
CompiledClassV1::try_from(pending_casm).map_err(StateError::ProgramError)?,
CompiledClassV1::try_from((
pending_casm,
SierraVersion::extract_from_program(&sierra.sierra_program)?,
))
.map_err(StateError::ProgramError)?,
);
let _sierra_version = SierraVersion::extract_from_program(&sierra.sierra_program)?;
// TODO(AVIV): Use the sierra version when the return type is updated.
return Ok(runnable_compiled_class);
}
}
Expand Down
13 changes: 9 additions & 4 deletions crates/papyrus_execution/src/state_reader_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand All @@ -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());
Expand All @@ -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());
Expand Down
8 changes: 5 additions & 3 deletions crates/papyrus_state_reader/src/papyrus_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ impl PapyrusReader {
&self,
class_hash: ClassHash,
) -> StateResult<VersionedRunnableCompiledClass> {
// TODO(AVIV): Return RunnableCompiledClass.
let state_number = StateNumber(self.latest_block);
let class_declaration_block_number = self
.reader()?
Expand All @@ -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)));
}

Expand Down
10 changes: 6 additions & 4 deletions crates/starknet_api/src/contract_class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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(),
}
}

Expand Down
5 changes: 3 additions & 2 deletions crates/starknet_gateway/src/compilation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()).into();

Ok(ClassInfo {
contract_class: ContractClass::V1(casm_contract_class),
sierra_program_length: rpc_contract_class.sierra_program.len(),
Expand Down
6 changes: 3 additions & 3 deletions crates/starknet_gateway/src/rpc_state_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +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::contract_class::VersionedCasm;
use starknet_api::core::{ClassHash, CompiledClassHash, ContractAddress, Nonce};
use starknet_api::state::StorageKey;
use starknet_types_core::felt::Felt;
Expand Down Expand Up @@ -145,11 +145,11 @@ impl BlockifierStateReader for RpcStateReader {

let result =
self.send_rpc_request("starknet_getCompiledContractClass", get_compiled_class_params)?;
let (contract_class, _): (CompiledContractClass, SierraVersion) =
let versioned_casm: VersionedCasm =
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(versioned_casm).map_err(StateError::ProgramError)?,
)),
CompiledContractClass::V0(contract_class_v0) => Ok(RunnableCompiledClass::V0(
CompiledClassV0::try_from(contract_class_v0).map_err(StateError::ProgramError)?,
Expand Down
Loading

0 comments on commit 1683c47

Please sign in to comment.