Skip to content

Commit

Permalink
feat(blockifier): integrate Casm read from class manager client
Browse files Browse the repository at this point in the history
Chose this simpler option to implement, instead of making Papyrus state
generic by `CR: CasmReader` trait, since it would require cloning `mdbx`
resources, which is flaky working with PyO3.

After `native_blockifier` is deprecated, the client should become
non-`Option` and Papyrus state (in the new Batcher) should always be initialized
with a concrete instance.
  • Loading branch information
elintul committed Feb 5, 2025
1 parent 169b5a6 commit 7e1b2e7
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 19 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/papyrus_state_reader/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ workspace = true
[dependencies]
blockifier.workspace = true
cairo-lang-starknet-classes.workspace = true
futures.workspace = true
papyrus_storage.workspace = true
starknet-types-core.workspace = true
starknet_api.workspace = true
Expand Down
67 changes: 48 additions & 19 deletions crates/papyrus_state_reader/src/papyrus_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@ use blockifier::state::global_cache::CachedCairoNative;
use blockifier::state::global_cache::CachedCasm;
use blockifier::state::state_api::{StateReader, StateResult};
use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass;
use futures::executor::block_on;
use papyrus_storage::compiled_class::CasmStorageReader;
use papyrus_storage::db::RO;
use papyrus_storage::state::StateStorageReader;
use papyrus_storage::StorageReader;
use starknet_api::block::BlockNumber;
use starknet_api::contract_class::SierraVersion;
use starknet_api::contract_class::{ContractClass, SierraVersion};
use starknet_api::core::{ClassHash, CompiledClassHash, ContractAddress, Nonce};
use starknet_api::deprecated_contract_class::ContractClass as DeprecatedClass;
use starknet_api::state::{SierraContractClass, StateNumber, StorageKey};
Expand All @@ -34,7 +35,8 @@ pub struct PapyrusReader {
storage_reader: StorageReader,
latest_block: BlockNumber,
contract_class_manager: ContractClassManager,
_class_reader: SharedClassManagerClient,
// Reader is `None` for reader invoked through `native_blockifier`.
class_reader: Option<SharedClassManagerClient>,
}

impl PapyrusReader {
Expand All @@ -43,9 +45,13 @@ impl PapyrusReader {
latest_block: BlockNumber,
contract_class_manager: ContractClassManager,
) -> Self {
// TODO(Elin): integrate class manager client.
let _class_reader = Arc::new(EmptyClassManagerClient);
Self { storage_reader, latest_block, contract_class_manager, _class_reader }
Self {
storage_reader,
latest_block,
contract_class_manager,
// TODO(Elin): integrate class manager client.
class_reader: None,
}
}

fn reader(&self) -> StateResult<RawPapyrusReader<'_>> {
Expand Down Expand Up @@ -144,28 +150,51 @@ impl PapyrusReader {
&self,
class_hash: ClassHash,
) -> StateResult<(CasmContractClass, SierraContractClass)> {
let (option_casm, option_sierra) = self
.reader()?
.get_casm_and_sierra(&class_hash)
let Some(class_reader) = &self.class_reader else {
let (option_casm, option_sierra) = self
.reader()?
.get_casm_and_sierra(&class_hash)
.map_err(|err| StateError::StateReadError(err.to_string()))?;
let (casm, sierra) = couple_casm_and_sierra(class_hash, option_casm, option_sierra)?
.expect(
"Should be able to fetch a Casm and Sierra class if its definition exists,
database is inconsistent.",
);

return Ok((casm, sierra));
};

let casm = block_on(class_reader.get_executable(class_hash))
.map_err(|err| StateError::StateReadError(err.to_string()))?;
let ContractClass::V1((casm, _sierra_version)) = casm else {
panic!("Class hash {class_hash} originated from a Cairo 1 contract.");
};
// TODO(Elin): consider not reading Sierra if compilation is disabled.
let sierra = block_on(class_reader.get_sierra(class_hash))
.map_err(|err| StateError::StateReadError(err.to_string()))?;
let (casm, sierra) = couple_casm_and_sierra(class_hash, option_casm, option_sierra)?
.expect(
"Should be able to fetch a Casm and Sierra class if its definition exists,
database is inconsistent.",
);

Ok((casm, sierra))
}

fn read_deprecated_casm(&self, class_hash: ClassHash) -> StateResult<Option<DeprecatedClass>> {
let state_number = StateNumber(self.latest_block);
let option_casm = self
.reader()?
.get_state_reader()
.and_then(|sr| sr.get_deprecated_class_definition_at(state_number, &class_hash))
let Some(class_reader) = &self.class_reader else {
let state_number = StateNumber(self.latest_block);
let option_casm = self
.reader()?
.get_state_reader()
.and_then(|sr| sr.get_deprecated_class_definition_at(state_number, &class_hash))
.map_err(|err| StateError::StateReadError(err.to_string()))?;

return Ok(option_casm);
};

let casm = block_on(class_reader.get_executable(class_hash))
.map_err(|err| StateError::StateReadError(err.to_string()))?;
let ContractClass::V0(casm) = casm else {
panic!("Class hash {class_hash} originated from a Cairo 0 contract.");
};

Ok(option_casm)
Ok(Some(casm))
}
}

Expand Down
2 changes: 2 additions & 0 deletions crates/starknet_class_manager_types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ pub struct ClassHashes {
pub trait ClassManagerClient: Send + Sync {
async fn add_class(&self, class: Class) -> ClassManagerClientResult<ClassHashes>;

// TODO(Elin): separate V0 and V1 APIs; remove Sierra version.
async fn get_executable(&self, class_id: ClassId) -> ClassManagerClientResult<ExecutableClass>;

async fn get_sierra(&self, class_id: ClassId) -> ClassManagerClientResult<Class>;
Expand All @@ -75,6 +76,7 @@ pub enum CachedClassStorageError<E: Error> {
Storage(#[from] E),
}

// TODO(Elin): express class not found, either as `Option`, or as a dedicated error variant.
#[derive(Clone, Debug, Error, Eq, PartialEq, Serialize, Deserialize)]
pub enum ClassManagerError {
#[error("Internal client error: {0}")]
Expand Down

0 comments on commit 7e1b2e7

Please sign in to comment.