Skip to content

Commit

Permalink
feat(starknet_state_sync): implement state sync get compiled class
Browse files Browse the repository at this point in the history
  • Loading branch information
noamsp-starkware committed Dec 22, 2024
1 parent f7ff380 commit 3debc32
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 6 deletions.
17 changes: 15 additions & 2 deletions crates/starknet_gateway/src/sync_state_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use blockifier::state::errors::StateError;
use blockifier::state::state_api::{StateReader as BlockifierStateReader, StateResult};
use futures::executor::block_on;
use starknet_api::block::{BlockInfo, BlockNumber};
use starknet_api::contract_class::ContractClass;
use starknet_api::core::{ClassHash, CompiledClassHash, ContractAddress, Nonce};
use starknet_api::state::StorageKey;
use starknet_state_sync_types::communication::SharedStateSyncClient;
Expand Down Expand Up @@ -55,8 +56,20 @@ impl BlockifierStateReader for SyncStateReader {
Ok(res)
}

fn get_compiled_class(&self, _class_hash: ClassHash) -> StateResult<RunnableCompiledClass> {
todo!()
fn get_compiled_class(&self, class_hash: ClassHash) -> StateResult<RunnableCompiledClass> {
let contract_class = block_on(
self.state_sync_client.get_compiled_class_deprecated(self.block_number, class_hash),
)
.map_err(|e| StateError::StateReadError(e.to_string()))?;

match contract_class {
ContractClass::V1(casm_contract_class) => {
Ok(RunnableCompiledClass::V1(casm_contract_class.try_into()?))
}
ContractClass::V0(deprecated_contract_class) => {
Ok(RunnableCompiledClass::V0(deprecated_contract_class.try_into()?))
}
}
}

fn get_class_hash_at(&self, contract_address: ContractAddress) -> StateResult<ClassHash> {
Expand Down
47 changes: 47 additions & 0 deletions crates/starknet_state_sync/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ pub mod runner;

use async_trait::async_trait;
use papyrus_storage::body::BodyStorageReader;
use papyrus_storage::compiled_class::CasmStorageReader;
use papyrus_storage::db::TransactionKind;
use papyrus_storage::state::StateStorageReader;
use papyrus_storage::{StorageReader, StorageTxn};
use starknet_api::block::BlockNumber;
use starknet_api::contract_class::{ContractClass, SierraVersion};
use starknet_api::core::{ClassHash, ContractAddress, Nonce, BLOCK_HASH_TABLE_ADDRESS};
use starknet_api::state::{StateNumber, StorageKey};
use starknet_sequencer_infra::component_definitions::{ComponentRequestHandler, ComponentStarter};
Expand Down Expand Up @@ -55,6 +57,11 @@ impl ComponentRequestHandler<StateSyncRequest, StateSyncResponse> for StateSync
self.get_class_hash_at(block_number, contract_address),
)
}
StateSyncRequest::GetCompiledClassDeprecated(block_number, class_hash) => {
StateSyncResponse::GetCompiledClassDeprecated(
self.get_compiled_class_deprecated(block_number, class_hash),
)
}
}
}
}
Expand Down Expand Up @@ -134,6 +141,46 @@ impl StateSync {
.ok_or(StateSyncError::ContractNotFound(contract_address))?;
Ok(class_hash)
}

fn get_compiled_class_deprecated(
&self,
block_number: BlockNumber,
class_hash: ClassHash,
) -> StateSyncResult<ContractClass> {
let txn = self.storage_reader.begin_ro_txn()?;
let latest_block_number = txn.get_compiled_class_marker()?.prev();
if latest_block_number.is_none_or(|latest_block_number| latest_block_number < block_number)
{
return Err(StateSyncError::BlockNotFound(block_number));
}

let state_reader = txn.get_state_reader()?;

// Check if this class exists in the Cairo1 classes table.
if let Some(class_definition_block_number) =
state_reader.get_class_definition_block_number(&class_hash)?
{
if class_definition_block_number > block_number {
return Err(StateSyncError::ClassNotFound(class_hash));
}

let (option_casm, option_sierra) = txn.get_casm_and_sierra(&class_hash)?;

// Check if both options are `Some`. If not, since we verified the block number is
// smaller than the casm marker, we return that the class doesnt exist.
let (casm, sierra) =
option_casm.zip(option_sierra).ok_or(StateSyncError::ClassNotFound(class_hash))?;
let sierra_version = SierraVersion::extract_from_program(&sierra.sierra_program)?;
return Ok(ContractClass::V1((casm, sierra_version)));
}

// Check if this class exists in the Cairo0 classes table.
let state_number = StateNumber::unchecked_right_after_block(block_number);
let deprecated_compiled_contract_class = state_reader
.get_deprecated_class_definition_at(state_number, &class_hash)?
.ok_or(StateSyncError::ClassNotFound(class_hash))?;
Ok(ContractClass::V0(deprecated_compiled_contract_class))
}
}

fn verify_synced_up_to<Mode: TransactionKind>(
Expand Down
41 changes: 40 additions & 1 deletion crates/starknet_state_sync_types/src/communication.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use async_trait::async_trait;
use papyrus_proc_macros::handle_response_variants;
use serde::{Deserialize, Serialize};
use starknet_api::block::BlockNumber;
use starknet_api::contract_class::ContractClass;
use starknet_api::core::{ClassHash, ContractAddress, Nonce};
use starknet_api::state::StorageKey;
use starknet_sequencer_infra::component_client::{
Expand Down Expand Up @@ -56,7 +57,13 @@ pub trait StateSyncClient: Send + Sync {
contract_address: ContractAddress,
) -> StateSyncClientResult<ClassHash>;

// TODO: Add get_compiled_class for StateSyncReader
// TODO: Remove this and fix sync state reader once the compiler component is ready.
async fn get_compiled_class_deprecated(
&self,
block_number: BlockNumber,
class_hash: ClassHash,
) -> StateSyncClientResult<ContractClass>;

// TODO: Add get_compiled_class_hash for StateSyncReader
// TODO: Add get_block_info for StateSyncReader
}
Expand All @@ -83,6 +90,7 @@ pub enum StateSyncRequest {
GetStorageAt(BlockNumber, ContractAddress, StorageKey),
GetNonceAt(BlockNumber, ContractAddress),
GetClassHashAt(BlockNumber, ContractAddress),
GetCompiledClassDeprecated(BlockNumber, ClassHash),
}

#[derive(Clone, Debug, Serialize, Deserialize)]
Expand All @@ -92,6 +100,7 @@ pub enum StateSyncResponse {
GetStorageAt(StateSyncResult<Felt>),
GetNonceAt(StateSyncResult<Nonce>),
GetClassHashAt(StateSyncResult<ClassHash>),
GetCompiledClassDeprecated(StateSyncResult<ContractClass>),
}

#[async_trait]
Expand Down Expand Up @@ -165,6 +174,21 @@ impl StateSyncClient for LocalStateSyncClient {
StateSyncError
)
}

async fn get_compiled_class_deprecated(
&self,
block_number: BlockNumber,
class_hash: ClassHash,
) -> StateSyncClientResult<ContractClass> {
let request = StateSyncRequest::GetCompiledClassDeprecated(block_number, class_hash);
let response = self.send(request).await;
handle_response_variants!(
StateSyncResponse,
GetCompiledClassDeprecated,
StateSyncClientError,
StateSyncError
)
}
}

#[async_trait]
Expand Down Expand Up @@ -238,4 +262,19 @@ impl StateSyncClient for RemoteStateSyncClient {
StateSyncError
)
}

async fn get_compiled_class_deprecated(
&self,
block_number: BlockNumber,
class_hash: ClassHash,
) -> StateSyncClientResult<ContractClass> {
let request = StateSyncRequest::GetCompiledClassDeprecated(block_number, class_hash);
let response = self.send(request).await;
handle_response_variants!(
StateSyncResponse,
GetCompiledClassDeprecated,
StateSyncClientError,
StateSyncError
)
}
}
17 changes: 14 additions & 3 deletions crates/starknet_state_sync_types/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use papyrus_storage::StorageError;
use serde::{Deserialize, Serialize};
use starknet_api::block::BlockNumber;
use starknet_api::core::ContractAddress;
use starknet_api::core::{ClassHash, ContractAddress};
use starknet_api::StarknetApiError;
use thiserror::Error;

#[derive(Debug, Error, Serialize, Deserialize, Clone)]
Expand All @@ -12,14 +13,24 @@ pub enum StateSyncError {
BlockNotFound(BlockNumber),
#[error("Contract address {0} was not found")]
ContractNotFound(ContractAddress),
// StorageError does not derive Serialize, Deserialize and Clone Traits.
// We put the string of the error instead.
#[error("Class hash {0} was not found")]
ClassNotFound(ClassHash),
// StorageError and StarknetApiError do not derive Serialize, Deserialize and Clone Traits.
// We put the string of the errors instead.
#[error("Unexpected storage error: {0}")]
StorageError(String),
#[error("Unexpected starknet api error: {0}")]
StarknetApiError(String),
}

impl From<StorageError> for StateSyncError {
fn from(error: StorageError) -> Self {
StateSyncError::StorageError(error.to_string())
}
}

impl From<StarknetApiError> for StateSyncError {
fn from(error: StarknetApiError) -> Self {
StateSyncError::StarknetApiError(error.to_string())
}
}

0 comments on commit 3debc32

Please sign in to comment.