Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(starknet_state_sync): implement state sync get compiled class #2817

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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())
}
}