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 sync state reader get storage at #2755

Open
wants to merge 1 commit into
base: noam.s/sync_state_reader_infra
Choose a base branch
from
Open
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
4 changes: 4 additions & 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/blockifier/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ stacker = { workspace = true, optional = true }
starknet-types-core.workspace = true
starknet_api.workspace = true
starknet_sierra_compile = { workspace = true, optional = true }
starknet_state_sync_types.workspace = true
strum.workspace = true
strum_macros.workspace = true
tempfile.workspace = true
Expand Down
3 changes: 3 additions & 0 deletions crates/blockifier/src/state/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use num_bigint::{BigUint, TryFromBigIntError};
use starknet_api::core::{ClassHash, ContractAddress};
use starknet_api::state::SierraContractClass;
use starknet_api::StarknetApiError;
use starknet_state_sync_types::communication::StateSyncClientError;
use thiserror::Error;

use crate::abi::constants;
Expand Down Expand Up @@ -32,6 +33,8 @@ pub enum StateError {
/// Represents all unexpected errors that may occur while reading from state.
#[error("Failed to read from state: {0}.")]
StateReadError(String),
#[error(transparent)]
StateSyncClientError(#[from] StateSyncClientError),
}

/// Ensures that the CASM and Sierra classes are coupled - Meaning that they both exist or are
Expand Down
1 change: 1 addition & 0 deletions crates/starknet_gateway/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ async-trait.workspace = true
axum.workspace = true
blockifier = { workspace = true, features = ["testing"] }
cairo-lang-starknet-classes.workspace = true
futures.workspace = true
mempool_test_utils.workspace = true
papyrus_config.workspace = true
papyrus_network_types.workspace = true
Expand Down
13 changes: 10 additions & 3 deletions crates/starknet_gateway/src/sync_state_reader.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use blockifier::execution::contract_class::RunnableCompiledClass;
use blockifier::state::state_api::{StateReader as BlockifierStateReader, StateResult};
use futures::executor::block_on;
use starknet_api::block::{BlockInfo, BlockNumber};
use starknet_api::core::{ClassHash, CompiledClassHash, ContractAddress, Nonce};
use starknet_api::state::StorageKey;
Expand Down Expand Up @@ -32,10 +33,16 @@ impl MempoolStateReader for SyncStateReader {
impl BlockifierStateReader for SyncStateReader {
fn get_storage_at(
&self,
_contract_address: ContractAddress,
_key: StorageKey,
contract_address: ContractAddress,
key: StorageKey,
) -> StateResult<Felt> {
todo!()
let res = block_on(self.shared_state_sync_client.get_storage_at(
self.block_number,
contract_address,
key,
))?;

Ok(res.unwrap_or_default())
}

fn get_nonce_at(&self, _contract_address: ContractAddress) -> StateResult<Nonce> {
Expand Down
1 change: 1 addition & 0 deletions crates/starknet_state_sync/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ papyrus_network.workspace = true
papyrus_p2p_sync.workspace = true
papyrus_storage.workspace = true
serde.workspace = true
starknet-types-core.workspace = true
starknet_api = { workspace = true, features = ["testing"] }
starknet_sequencer_infra.workspace = true
starknet_state_sync_types.workspace = true
Expand Down
39 changes: 39 additions & 0 deletions crates/starknet_state_sync/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,18 @@ use papyrus_storage::body::BodyStorageReader;
use papyrus_storage::state::StateStorageReader;
use papyrus_storage::StorageReader;
use starknet_api::block::BlockNumber;
use starknet_api::core::{ContractAddress, 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};
use starknet_state_sync_types::communication::{
StateSyncRequest,
StateSyncResponse,
StateSyncResult,
};
use starknet_state_sync_types::errors::StateSyncError;
use starknet_state_sync_types::state_sync_types::SyncBlock;
use starknet_types_core::felt::Felt;

use crate::config::StateSyncConfig;
use crate::runner::StateSyncRunner;
Expand All @@ -39,6 +43,13 @@ impl ComponentRequestHandler<StateSyncRequest, StateSyncResponse> for StateSync
StateSyncRequest::AddNewBlock(_block_number, _sync_block) => {
todo!()
}
StateSyncRequest::GetStorageAt(block_number, contract_address, storage_key) => {
StateSyncResponse::GetStorageAt(self.get_storage_at(
block_number,
contract_address,
storage_key,
))
}
}
}
}
Expand All @@ -58,6 +69,34 @@ impl StateSync {

Ok(None)
}

fn get_storage_at(
&self,
block_number: BlockNumber,
contract_address: ContractAddress,
storage_key: StorageKey,
) -> StateSyncResult<Option<Felt>> {
let txn = self.storage_reader.begin_ro_txn()?;

if let Some(state_number) = StateNumber::right_after_block(block_number) {
let state_reader = txn.get_state_reader()?;
let res = state_reader.get_storage_at(state_number, &contract_address, &storage_key)?;

// If the contract is not deployed, res will be 0. Checking if that's the case so
// that we'll return an error instead.
// Contract address 0x1 is a special address, it stores the block
// hashes. Contracts are not deployed to this address.
if res == Felt::default() && contract_address != BLOCK_HASH_TABLE_ADDRESS {
// check if the contract exists
state_reader.get_class_hash_at(state_number, &contract_address)?.ok_or_else(
|| StateSyncError::StorageError("Contract not found".to_string()),
)?;
}
return Ok(Some(res));
}

Ok(None)
}
}

pub type LocalStateSyncServer =
Expand Down
1 change: 1 addition & 0 deletions crates/starknet_state_sync_types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ async-trait.workspace = true
papyrus_proc_macros.workspace = true
papyrus_storage.workspace = true
serde = { workspace = true, features = ["derive"] }
starknet-types-core.workspace = true
starknet_api.workspace = true
starknet_sequencer_infra.workspace = true
thiserror.workspace = true
45 changes: 44 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,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;
use starknet_api::state::StorageKey;
use starknet_sequencer_infra::component_client::{
ClientError,
LocalComponentClient,
Expand All @@ -13,6 +15,7 @@ use starknet_sequencer_infra::component_definitions::{
ComponentClient,
ComponentRequestAndResponseSender,
};
use starknet_types_core::felt::Felt;
use thiserror::Error;

use crate::errors::StateSyncError;
Expand All @@ -34,7 +37,13 @@ pub trait StateSyncClient: Send + Sync {
sync_block: SyncBlock,
) -> StateSyncClientResult<()>;

// TODO: add get_storage_at for BlockifierStateReader trait
async fn get_storage_at(
&self,
block_number: BlockNumber,
contract_address: ContractAddress,
storage_key: StorageKey,
) -> StateSyncClientResult<Option<Felt>>;

// TODO: add get_nonce_at for BlockifierStateReader trait
// TODO: add get_compiled_class for BlockifierStateReader trait
// TODO: add get_class_hash_at for BlockifierStateReader trait
Expand Down Expand Up @@ -63,12 +72,14 @@ pub type StateSyncRequestAndResponseSender =
pub enum StateSyncRequest {
GetBlock(BlockNumber),
AddNewBlock(BlockNumber, SyncBlock),
GetStorageAt(BlockNumber, ContractAddress, StorageKey),
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum StateSyncResponse {
GetBlock(StateSyncResult<Option<SyncBlock>>),
AddNewBlock(StateSyncResult<()>),
GetStorageAt(StateSyncResult<Option<Felt>>),
}

#[async_trait]
Expand Down Expand Up @@ -96,6 +107,22 @@ impl StateSyncClient for LocalStateSyncClient {
StateSyncError
)
}

async fn get_storage_at(
&self,
block_number: BlockNumber,
contract_address: ContractAddress,
storage_key: StorageKey,
) -> StateSyncClientResult<Option<Felt>> {
let request = StateSyncRequest::GetStorageAt(block_number, contract_address, storage_key);
let response = self.send(request).await;
handle_response_variants!(
StateSyncResponse,
GetStorageAt,
StateSyncClientError,
StateSyncError
)
}
}

#[async_trait]
Expand Down Expand Up @@ -123,4 +150,20 @@ impl StateSyncClient for RemoteStateSyncClient {
StateSyncError
)
}

async fn get_storage_at(
&self,
block_number: BlockNumber,
contract_address: ContractAddress,
storage_key: StorageKey,
) -> StateSyncClientResult<Option<Felt>> {
let request = StateSyncRequest::GetStorageAt(block_number, contract_address, storage_key);
let response = self.send(request).await;
handle_response_variants!(
StateSyncResponse,
GetStorageAt,
StateSyncClientError,
StateSyncError
)
}
}
Loading