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 19, 2024
1 parent 8f57ae7 commit 3f28e7c
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 8 deletions.
16 changes: 14 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,19 @@ 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, _sierra_version) =
block_on(self.state_sync_client.get_compiled_class(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
44 changes: 43 additions & 1 deletion crates/starknet_state_sync/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ 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::core::{ContractAddress, Nonce, BLOCK_HASH_TABLE_ADDRESS};
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};
use starknet_sequencer_infra::component_server::{LocalComponentServer, RemoteComponentServer};
Expand Down Expand Up @@ -54,6 +56,11 @@ impl ComponentRequestHandler<StateSyncRequest, StateSyncResponse> for StateSync
StateSyncRequest::GetNonceAt(block_number, contract_address) => {
StateSyncResponse::GetNonceAt(self.get_nonce_at(block_number, contract_address))
}
StateSyncRequest::GetCompiledClass(block_number, class_hash) => {
StateSyncResponse::GetCompiledClass(
self.get_compiled_class(block_number, class_hash),
)
}
}
}
}
Expand Down Expand Up @@ -117,6 +124,41 @@ impl StateSync {

Ok(res)
}

fn get_compiled_class(
&self,
block_number: BlockNumber,
class_hash: ClassHash,
) -> StateSyncResult<(ContractClass, SierraVersion)> {
let txn = self.storage_reader.begin_ro_txn()?;
verify_synced_up_to(&txn, 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::ClassHashNotFound(class_hash));
}
let (option_casm, option_sierra) = txn.get_casm_and_sierra(&class_hash)?;

// Check if both options are `Some`.
let (casm, sierra) = option_casm
.zip(option_sierra)
.ok_or(StateSyncError::ClassHashNotFound(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::ClassHashNotFound(class_hash))?;

Ok((ContractClass::V0(deprecated_compiled_contract_class), SierraVersion::DEPRECATED))
}
}

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

// TODO: Add get_compiled_class for StateSyncReader
async fn get_compiled_class(
&self,
block_number: BlockNumber,
class_hash: ClassHash,
) -> StateSyncClientResult<(ContractClass, SierraVersion)>;

// TODO: Add get_class_hash_at for StateSyncReader
// TODO: Add get_compiled_class_hash for StateSyncReader
// TODO: Add get_block_info for StateSyncReader
Expand Down Expand Up @@ -79,6 +85,7 @@ pub enum StateSyncRequest {
AddNewBlock(BlockNumber, SyncBlock),
GetStorageAt(BlockNumber, ContractAddress, StorageKey),
GetNonceAt(BlockNumber, ContractAddress),
GetCompiledClass(BlockNumber, ClassHash),
}

#[derive(Clone, Debug, Serialize, Deserialize)]
Expand All @@ -87,6 +94,7 @@ pub enum StateSyncResponse {
AddNewBlock(StateSyncResult<()>),
GetStorageAt(StateSyncResult<Felt>),
GetNonceAt(StateSyncResult<Nonce>),
GetCompiledClass(StateSyncResult<(ContractClass, SierraVersion)>),
}

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

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

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

async fn get_compiled_class(
&self,
block_number: BlockNumber,
class_hash: ClassHash,
) -> StateSyncClientResult<(ContractClass, SierraVersion)> {
let request = StateSyncRequest::GetCompiledClass(block_number, class_hash);
let response = self.send(request).await;
handle_response_variants!(
StateSyncResponse,
GetCompiledClass,
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")]
ClassHashNotFound(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 3f28e7c

Please sign in to comment.