Skip to content

Commit

Permalink
chore(cairo_native): add the compilation of native to the flow
Browse files Browse the repository at this point in the history
  • Loading branch information
meship-starkware committed Dec 24, 2024
1 parent 440c12c commit e42fa94
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 22 deletions.
10 changes: 10 additions & 0 deletions crates/blockifier/src/state/contract_class_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,16 @@ impl ContractClassManager {
self.contract_caches.set_casm(class_hash, compiled_class);
}

#[cfg(feature = "cairo_native")]
pub fn run_cairo_native(&self) -> bool {
self.config.run_cairo_native
}

#[cfg(feature = "cairo_native")]
pub fn wait_on_native_compilation(&self) -> bool {
self.config.wait_on_native_compilation
}

/// Clear the contract caches.
pub fn clear(&mut self) {
self.contract_caches.clear();
Expand Down
7 changes: 7 additions & 0 deletions crates/blockifier/src/state/global_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ pub enum CachedCasm {
WithoutSierra(RunnableCompiledClass),
WithSierra(RunnableCompiledClass, Arc<SierraContractClass>),
}
impl CachedCasm {
pub fn casm(&self) -> RunnableCompiledClass {
match self {
CachedCasm::WithoutSierra(casm) | CachedCasm::WithSierra(casm, _) => casm.clone(),
}
}
}

#[cfg(feature = "cairo_native")]
#[derive(Debug, Clone)]
Expand Down
2 changes: 1 addition & 1 deletion crates/native_blockifier/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ license-file.workspace = true
description = "A Bridge between the Rust blockifier crate and Python."

[features]
cairo_native = ["blockifier/cairo_native"]
cairo_native = ["blockifier/cairo_native", "papyrus_state_reader/cairo_native"]
# Required for `cargo test` to work with Pyo3.
# On Python, make sure to compile this with the extension-module feature enabled.
# https://pyo3.rs/v0.19.1/faq#i-cant-run-cargo-test-or-i-cant-build-in-a-cargo-workspace-im-having-linker-issues-like-symbol-not-found-or-undefined-reference-to-_pyexc_systemerror
Expand Down
3 changes: 3 additions & 0 deletions crates/papyrus_state_reader/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ edition.workspace = true
repository.workspace = true
license.workspace = true

[features]
cairo_native = ["blockifier/cairo_native"]

[lints]
workspace = true

Expand Down
120 changes: 99 additions & 21 deletions crates/papyrus_state_reader/src/papyrus_state.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
use std::sync::Arc;

use blockifier::execution::contract_class::{
CompiledClassV0,
CompiledClassV1,
RunnableCompiledClass,
};
use blockifier::state::contract_class_manager::ContractClassManager;
use blockifier::state::errors::{couple_casm_and_sierra, StateError};
#[cfg(feature = "cairo_native")]
use blockifier::state::global_cache::CachedCairoNative;
use blockifier::state::global_cache::CachedCasm;
use blockifier::state::state_api::{StateReader, StateResult};
use papyrus_storage::compiled_class::CasmStorageReader;
Expand All @@ -22,6 +26,7 @@ use starknet_types_core::felt::Felt;
mod test;

type RawPapyrusReader<'env> = papyrus_storage::StorageTxn<'env, RO>;

pub struct PapyrusReader {
storage_reader: StorageReader,
latest_block: BlockNumber,
Expand All @@ -45,10 +50,7 @@ impl PapyrusReader {

/// Returns a V1 contract if found, or a V0 contract if a V1 contract is not
/// found, or an `Error` otherwise.
fn get_compiled_class_inner(
&self,
class_hash: ClassHash,
) -> StateResult<RunnableCompiledClass> {
fn get_compiled_class_inner(&self, class_hash: ClassHash) -> StateResult<CachedCasm> {
let state_number = StateNumber(self.latest_block);
let class_declaration_block_number = self
.reader()?
Expand All @@ -69,11 +71,11 @@ impl PapyrusReader {
database is inconsistent.",
);
let sierra_version = SierraVersion::extract_from_program(&sierra.sierra_program)?;
let runnable_compiled = RunnableCompiledClass::V1(CompiledClassV1::try_from((
let runnable_casm = RunnableCompiledClass::V1(CompiledClassV1::try_from((
casm_compiled_class,
sierra_version,
))?);
return Ok(runnable_compiled);
return Ok(CachedCasm::WithSierra(runnable_casm, Arc::new(sierra)));
}

let v0_compiled_class = self
Expand All @@ -83,12 +85,52 @@ impl PapyrusReader {
.map_err(|err| StateError::StateReadError(err.to_string()))?;

match v0_compiled_class {
Some(starknet_api_contract_class) => Ok(RunnableCompiledClass::V0(
CompiledClassV0::try_from(starknet_api_contract_class)?,
)),
Some(starknet_api_contract_class) => {
let runnable_casm = RunnableCompiledClass::V0(CompiledClassV0::try_from(
starknet_api_contract_class,
)?);
Ok(CachedCasm::WithoutSierra(runnable_casm))
}
None => Err(StateError::UndeclaredClassHash(class_hash)),
}
}

fn get_compiled_class_non_native_flow(
&self,
class_hash: ClassHash,
) -> StateResult<RunnableCompiledClass> {
let versioned_contract_class = self.contract_class_manager.get_casm(&class_hash);
match versioned_contract_class {
Some(contract_class) => Ok(contract_class.casm()),
None => {
let contract_class_from_db = self.get_compiled_class_inner(class_hash)?.casm();
self.contract_class_manager.set_casm(
class_hash,
CachedCasm::WithoutSierra(contract_class_from_db.clone()),
);
Ok(contract_class_from_db)
}
}
}

#[cfg(feature = "cairo_native")]
fn extract_contract_in_sync_compilation(
&self,
class_hash: ClassHash,
casm: RunnableCompiledClass,
) -> RunnableCompiledClass {
assert!(self.contract_class_manager.wait_on_native_compilation());
let cached_native = self
.contract_class_manager
.get_native(&class_hash)
.expect("Should have native in cache in sync compilation flow.");
match cached_native {
CachedCairoNative::Compiled(compiled_native) => {
RunnableCompiledClass::from(compiled_native)
}
CachedCairoNative::CompilationFailed => casm,
}
}
}

// Currently unused - will soon replace the same `impl` for `PapyrusStateReader`.
Expand Down Expand Up @@ -133,20 +175,56 @@ impl StateReader for PapyrusReader {

fn get_compiled_class(&self, class_hash: ClassHash) -> StateResult<RunnableCompiledClass> {
// Assumption: the global cache is cleared upon reverted blocks.
let cached_casm = self.contract_class_manager.get_casm(&class_hash);

match cached_casm {
None => {
let compiled_class_from_db = self.get_compiled_class_inner(class_hash)?;
self.contract_class_manager.set_casm(
class_hash,
CachedCasm::WithoutSierra(compiled_class_from_db.clone()),
);
Ok(compiled_class_from_db)
#[cfg(not(feature = "cairo_native"))]
return self.get_compiled_class_non_native_flow(class_hash);

#[cfg(feature = "cairo_native")]
{
// If we turned off the cairo native compilation, we use the non cairo native flow.
if !self.contract_class_manager.run_cairo_native() {
return self.get_compiled_class_non_native_flow(class_hash);
}
Some(CachedCasm::WithoutSierra(casm)) => Ok(casm),
Some(CachedCasm::WithSierra(_, _)) => {
todo!("Add this flow when Sierra to Native compilation is added to PapyrusReader.")

// We have the Native in cache.
if let Some(cached_native) = self.contract_class_manager.get_native(&class_hash) {
match cached_native {
CachedCairoNative::Compiled(compiled_native) => {
return Ok(RunnableCompiledClass::from(compiled_native));
}
// for some reason the compilation failed, we use the non cairo native flow.
CachedCairoNative::CompilationFailed => {
return self.get_compiled_class_non_native_flow(class_hash);
}
}
};

let cached_casm = match self.contract_class_manager.get_casm(&class_hash) {
// Casm is in cache.
Some(cached_casm) => cached_casm,
None => {
let cached_casm = self.get_compiled_class_inner(class_hash)?;
self.contract_class_manager.set_casm(class_hash, cached_casm.clone());
cached_casm
}
};

match cached_casm {
CachedCasm::WithSierra(runnable_casm, sierra) => {
if let RunnableCompiledClass::V1(casm_v1) = runnable_casm.clone() {
self.contract_class_manager.send_compilation_request((
class_hash,
sierra.clone(),
casm_v1.clone(),
));
if self.contract_class_manager.wait_on_native_compilation() {
return Ok(self
.extract_contract_in_sync_compilation(class_hash, runnable_casm));
}
}
Ok(runnable_casm)
}
CachedCasm::WithoutSierra(runnable_casm) => Ok(runnable_casm),
}
}
}
Expand Down

0 comments on commit e42fa94

Please sign in to comment.