diff --git a/Cargo.lock b/Cargo.lock index ed7c3ddd3..35cfe17ce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5458,7 +5458,6 @@ dependencies = [ "num-bigint", "num-traits 0.2.19", "papyrus_config", - "papyrus_rpc", "pretty_assertions", "reqwest", "rstest", @@ -5535,6 +5534,7 @@ dependencies = [ "starknet_mempool_infra", "starknet_mempool_node", "starknet_mempool_types", + "starknet_state_reader", "starknet_task_executor", "strum 0.24.1", "tempfile", @@ -5561,6 +5561,7 @@ dependencies = [ "starknet_mempool", "starknet_mempool_infra", "starknet_mempool_types", + "starknet_state_reader", "tokio", "tracing", "validator", @@ -5597,10 +5598,21 @@ dependencies = [ name = "starknet_state_reader" version = "0.0.0" dependencies = [ + "axum", "blockifier 0.8.0-rc.0 (git+https://github.com/starkware-libs/blockifier.git?rev=32191d41)", + "cairo-lang-starknet-classes", "mempool_test_utils", + "mockito", + "papyrus_config", + "papyrus_rpc", + "reqwest", + "serde", + "serde_json", "starknet-types-core", "starknet_api", + "thiserror", + "tokio", + "validator", ] [[package]] diff --git a/crates/gateway/Cargo.toml b/crates/gateway/Cargo.toml index 5f99737d6..e9fdb60af 100644 --- a/crates/gateway/Cargo.toml +++ b/crates/gateway/Cargo.toml @@ -21,7 +21,6 @@ hyper.workspace = true mempool_test_utils = { path = "../mempool_test_utils", version = "0.0" } num-traits.workspace = true papyrus_config.workspace = true -papyrus_rpc.workspace = true reqwest.workspace = true serde.workspace = true serde_json.workspace = true diff --git a/crates/gateway/src/config.rs b/crates/gateway/src/config.rs index 49970fa7a..68e90d662 100644 --- a/crates/gateway/src/config.rs +++ b/crates/gateway/src/config.rs @@ -147,33 +147,6 @@ impl SerializeConfig for StatelessTransactionValidatorConfig { } } -#[derive(Clone, Debug, Default, Serialize, Deserialize, Validate, PartialEq)] -pub struct RpcStateReaderConfig { - pub url: String, - pub json_rpc_version: String, -} - -#[cfg(any(feature = "testing", test))] -impl RpcStateReaderConfig { - pub fn create_for_testing() -> Self { - Self { url: "http://localhost:8080".to_string(), json_rpc_version: "2.0".to_string() } - } -} - -impl SerializeConfig for RpcStateReaderConfig { - fn dump(&self) -> BTreeMap { - BTreeMap::from_iter([ - ser_param("url", &self.url, "The url of the rpc server.", ParamPrivacyInput::Public), - ser_param( - "json_rpc_version", - &self.json_rpc_version, - "The json rpc version.", - ParamPrivacyInput::Public, - ), - ]) - } -} - // TODO(Arni): Remove this struct once Chain info supports Papyrus serialization. #[derive(Clone, Debug, Serialize, Deserialize, Validate, PartialEq)] pub struct ChainInfoConfig { diff --git a/crates/gateway/src/errors.rs b/crates/gateway/src/errors.rs index 75c30c0d6..f1994afcc 100644 --- a/crates/gateway/src/errors.rs +++ b/crates/gateway/src/errors.rs @@ -5,7 +5,7 @@ use blockifier::execution::errors::ContractClassError; use blockifier::state::errors::StateError; use blockifier::transaction::errors::TransactionExecutionError; use cairo_vm::types::errors::program_errors::ProgramError; -use serde_json::{Error as SerdeError, Value}; +use serde_json::Value; use starknet_api::block::{BlockNumber, GasPrice}; use starknet_api::core::CompiledClassHash; use starknet_api::transaction::{Resource, ResourceBounds}; @@ -134,24 +134,3 @@ pub enum RPCStateReaderError { #[error("Unexpected error code: {0}")] UnexpectedErrorCode(u16), } - -pub type RPCStateReaderResult = Result; - -impl From for StateError { - fn from(err: RPCStateReaderError) -> Self { - match err { - RPCStateReaderError::ClassHashNotFound(request) => { - match serde_json::from_value(request["params"]["class_hash"].clone()) { - Ok(class_hash) => StateError::UndeclaredClassHash(class_hash), - Err(e) => serde_err_to_state_err(e), - } - } - _ => StateError::StateReadError(err.to_string()), - } - } -} - -// Converts a serde error to the error type of the state reader. -pub fn serde_err_to_state_err(err: SerdeError) -> StateError { - StateError::StateReadError(format!("Failed to parse rpc result {:?}", err.to_string())) -} diff --git a/crates/gateway/src/gateway.rs b/crates/gateway/src/gateway.rs index 0d971413a..f9cb46fe9 100644 --- a/crates/gateway/src/gateway.rs +++ b/crates/gateway/src/gateway.rs @@ -11,13 +11,14 @@ use starknet_api::transaction::TransactionHash; use starknet_mempool_infra::component_runner::{ComponentStartError, ComponentStarter}; use starknet_mempool_types::communication::SharedMempoolClient; use starknet_mempool_types::mempool_types::{Account, MempoolInput}; +use starknet_state_reader::config::RpcStateReaderConfig; +use starknet_state_reader::rpc_state_reader::RpcStateReaderFactory; use starknet_state_reader::state_reader::StateReaderFactory; use tracing::{info, instrument}; use crate::compilation::GatewayCompiler; -use crate::config::{GatewayConfig, GatewayNetworkConfig, RpcStateReaderConfig}; +use crate::config::{GatewayConfig, GatewayNetworkConfig}; use crate::errors::{GatewayError, GatewayResult, GatewayRunError}; -use crate::rpc_state_reader::RpcStateReaderFactory; use crate::stateful_transaction_validator::StatefulTransactionValidator; use crate::stateless_transaction_validator::StatelessTransactionValidator; use crate::utils::{external_tx_to_thin_tx, get_sender_address}; diff --git a/crates/gateway/src/lib.rs b/crates/gateway/src/lib.rs index 4a724b5b9..45f1fb516 100644 --- a/crates/gateway/src/lib.rs +++ b/crates/gateway/src/lib.rs @@ -4,10 +4,6 @@ mod compiler_version; pub mod config; pub mod errors; pub mod gateway; -mod rpc_objects; -mod rpc_state_reader; -#[cfg(test)] -mod rpc_state_reader_test; mod stateful_transaction_validator; mod stateless_transaction_validator; diff --git a/crates/mempool_node/Cargo.toml b/crates/mempool_node/Cargo.toml index a4b562628..db9e40469 100644 --- a/crates/mempool_node/Cargo.toml +++ b/crates/mempool_node/Cargo.toml @@ -19,6 +19,7 @@ starknet_gateway = { path = "../gateway", version = "0.0" } starknet_mempool = { path = "../mempool", version = "0.0" } starknet_mempool_infra = { path = "../mempool_infra", version = "0.0" } starknet_mempool_types = { path = "../mempool_types", version = "0.0" } +starknet_state_reader = { path = "../state_reader", version = "0.0" } tokio.workspace = true tracing.workspace = true validator.workspace = true @@ -27,6 +28,6 @@ validator.workspace = true assert-json-diff.workspace = true assert_matches.workspace = true colored.workspace = true +mempool_test_utils = { path = "../mempool_test_utils" } pretty_assertions.workspace = true serde_json.workspace = true -mempool_test_utils = { path = "../mempool_test_utils" } diff --git a/crates/mempool_node/src/config/mod.rs b/crates/mempool_node/src/config/mod.rs index 3533d6a81..9fbd3a597 100644 --- a/crates/mempool_node/src/config/mod.rs +++ b/crates/mempool_node/src/config/mod.rs @@ -10,7 +10,8 @@ use papyrus_config::dumping::{append_sub_config_name, ser_param, SerializeConfig use papyrus_config::loading::load_and_process_config; use papyrus_config::{ConfigError, ParamPath, ParamPrivacyInput, SerializedParam}; use serde::{Deserialize, Serialize}; -use starknet_gateway::config::{GatewayConfig, RpcStateReaderConfig}; +use starknet_gateway::config::GatewayConfig; +use starknet_state_reader::config::RpcStateReaderConfig; use validator::{Validate, ValidationError}; use crate::version::VERSION_FULL; diff --git a/crates/state_reader/Cargo.toml b/crates/state_reader/Cargo.toml index 90f2236bc..90a9d304d 100644 --- a/crates/state_reader/Cargo.toml +++ b/crates/state_reader/Cargo.toml @@ -12,7 +12,20 @@ workspace = true testing = [] [dependencies] +axum.workspace = true blockifier = { workspace = true, features = ["testing"] } +cairo-lang-starknet-classes.workspace = true mempool_test_utils = { path = "../mempool_test_utils", version = "0.0" } +papyrus_config.workspace = true +papyrus_rpc.workspace = true +reqwest.workspace = true +serde.workspace = true +serde_json.workspace = true starknet-types-core.workspace = true starknet_api.workspace = true +thiserror.workspace = true +tokio.workspace = true +validator.workspace = true + +[dev-dependencies] +mockito.workspace = true diff --git a/crates/state_reader/src/config.rs b/crates/state_reader/src/config.rs new file mode 100644 index 000000000..04d055b1c --- /dev/null +++ b/crates/state_reader/src/config.rs @@ -0,0 +1,33 @@ +use std::collections::BTreeMap; + +use papyrus_config::dumping::{ser_param, SerializeConfig}; +use papyrus_config::{ParamPath, ParamPrivacyInput, SerializedParam}; +use serde::{Deserialize, Serialize}; +use validator::Validate; + +#[derive(Clone, Debug, Default, Serialize, Deserialize, Validate, PartialEq)] +pub struct RpcStateReaderConfig { + pub url: String, + pub json_rpc_version: String, +} + +#[cfg(any(feature = "testing", test))] +impl RpcStateReaderConfig { + pub fn create_for_testing() -> Self { + Self { url: "http://localhost:8080".to_string(), json_rpc_version: "2.0".to_string() } + } +} + +impl SerializeConfig for RpcStateReaderConfig { + fn dump(&self) -> BTreeMap { + BTreeMap::from_iter([ + ser_param("url", &self.url, "The url of the rpc server.", ParamPrivacyInput::Public), + ser_param( + "json_rpc_version", + &self.json_rpc_version, + "The json rpc version.", + ParamPrivacyInput::Public, + ), + ]) + } +} diff --git a/crates/state_reader/src/errors.rs b/crates/state_reader/src/errors.rs new file mode 100644 index 000000000..ebd35c2a7 --- /dev/null +++ b/crates/state_reader/src/errors.rs @@ -0,0 +1,44 @@ +use axum::http::StatusCode; +use blockifier::state::errors::StateError; +use serde_json::{Error as SerdeError, Value}; +use starknet_api::block::GasPrice; +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum RPCStateReaderError { + #[error("Block not found for request {0}")] + BlockNotFound(Value), + #[error("Class hash not found for request {0}")] + ClassHashNotFound(Value), + #[error("Failed to parse gas price {:?}", 0)] + GasPriceParsingFailure(GasPrice), + #[error("Contract address not found for request {0}")] + ContractAddressNotFound(Value), + #[error(transparent)] + ReqwestError(#[from] reqwest::Error), + #[error("RPC error: {0}")] + RPCError(StatusCode), + #[error("Unexpected error code: {0}")] + UnexpectedErrorCode(u16), +} + +pub type RPCStateReaderResult = Result; + +impl From for StateError { + fn from(err: RPCStateReaderError) -> Self { + match err { + RPCStateReaderError::ClassHashNotFound(request) => { + match serde_json::from_value(request["params"]["class_hash"].clone()) { + Ok(class_hash) => StateError::UndeclaredClassHash(class_hash), + Err(e) => serde_err_to_state_err(e), + } + } + _ => StateError::StateReadError(err.to_string()), + } + } +} + +// Converts a serde error to the error type of the state reader. +pub fn serde_err_to_state_err(err: SerdeError) -> StateError { + StateError::StateReadError(format!("Failed to parse rpc result {:?}", err.to_string())) +} diff --git a/crates/state_reader/src/lib.rs b/crates/state_reader/src/lib.rs index 96990f690..7b59f60f2 100644 --- a/crates/state_reader/src/lib.rs +++ b/crates/state_reader/src/lib.rs @@ -1,4 +1,7 @@ +pub mod config; +pub mod errors; +mod rpc_objects; +pub mod rpc_state_reader; pub mod state_reader; - #[cfg(any(feature = "testing", test))] pub mod state_reader_test_utils; diff --git a/crates/gateway/src/rpc_objects.rs b/crates/state_reader/src/rpc_objects.rs similarity index 100% rename from crates/gateway/src/rpc_objects.rs rename to crates/state_reader/src/rpc_objects.rs diff --git a/crates/gateway/src/rpc_state_reader.rs b/crates/state_reader/src/rpc_state_reader.rs similarity index 97% rename from crates/gateway/src/rpc_state_reader.rs rename to crates/state_reader/src/rpc_state_reader.rs index d83431a65..626f61dea 100644 --- a/crates/gateway/src/rpc_state_reader.rs +++ b/crates/state_reader/src/rpc_state_reader.rs @@ -1,3 +1,7 @@ +#[cfg(test)] +#[path = "rpc_state_reader_test.rs"] +mod rpc_state_reader_test; + use blockifier::blockifier::block::BlockInfo; use blockifier::execution::contract_class::{ContractClass, ContractClassV0, ContractClassV1}; use blockifier::state::errors::StateError; @@ -9,7 +13,6 @@ use serde_json::{json, Value}; use starknet_api::block::BlockNumber; use starknet_api::core::{ClassHash, CompiledClassHash, ContractAddress, Nonce}; use starknet_api::state::StorageKey; -use starknet_state_reader::state_reader::{MempoolStateReader, StateReaderFactory}; use starknet_types_core::felt::Felt; use crate::config::RpcStateReaderConfig; @@ -19,6 +22,7 @@ use crate::rpc_objects::{ GetCompiledContractClassParams, GetNonceParams, GetStorageAtParams, RpcResponse, RPC_CLASS_HASH_NOT_FOUND, RPC_ERROR_BLOCK_NOT_FOUND, RPC_ERROR_CONTRACT_ADDRESS_NOT_FOUND, }; +use crate::state_reader::{MempoolStateReader, StateReaderFactory}; pub struct RpcStateReader { pub config: RpcStateReaderConfig, diff --git a/crates/gateway/src/rpc_state_reader_test.rs b/crates/state_reader/src/rpc_state_reader_test.rs similarity index 99% rename from crates/gateway/src/rpc_state_reader_test.rs rename to crates/state_reader/src/rpc_state_reader_test.rs index 4d8144cbc..3596d484d 100644 --- a/crates/gateway/src/rpc_state_reader_test.rs +++ b/crates/state_reader/src/rpc_state_reader_test.rs @@ -7,7 +7,6 @@ use serde_json::json; use starknet_api::block::{BlockNumber, GasPrice}; use starknet_api::core::{ClassHash, ContractAddress, Nonce, PatriciaKey}; use starknet_api::{class_hash, contract_address, felt, patricia_key}; -use starknet_state_reader::state_reader::MempoolStateReader; use crate::config::RpcStateReaderConfig; use crate::rpc_objects::{ @@ -16,6 +15,7 @@ use crate::rpc_objects::{ RpcSuccessResponse, }; use crate::rpc_state_reader::RpcStateReader; +use crate::state_reader::MempoolStateReader; async fn run_rpc_server() -> mockito::ServerGuard { mockito::Server::new_async().await diff --git a/crates/tests-integration/Cargo.toml b/crates/tests-integration/Cargo.toml index fbebb917b..636e75315 100644 --- a/crates/tests-integration/Cargo.toml +++ b/crates/tests-integration/Cargo.toml @@ -27,6 +27,7 @@ starknet_gateway = { path = "../gateway", version = "0.0", features = ["testing" starknet_mempool_infra = { path = "../mempool_infra", version = "0.0" } starknet_mempool_node = { path = "../mempool_node", version = "0.0" } starknet_mempool_types = { path = "../mempool_types", version = "0.0" } +starknet_state_reader = { path = "../state_reader", version = "0.0" } starknet_task_executor = { path = "../task_executor", version = "0.0" } strum.workspace = true tempfile.workspace = true diff --git a/crates/tests-integration/src/integration_test_utils.rs b/crates/tests-integration/src/integration_test_utils.rs index b9ebcbdb4..b65d6e2a9 100644 --- a/crates/tests-integration/src/integration_test_utils.rs +++ b/crates/tests-integration/src/integration_test_utils.rs @@ -9,11 +9,12 @@ use reqwest::{Client, Response}; use starknet_api::rpc_transaction::RPCTransaction; use starknet_api::transaction::TransactionHash; use starknet_gateway::config::{ - GatewayConfig, GatewayNetworkConfig, RpcStateReaderConfig, StatefulTransactionValidatorConfig, + GatewayConfig, GatewayNetworkConfig, StatefulTransactionValidatorConfig, StatelessTransactionValidatorConfig, }; use starknet_gateway::errors::GatewayError; use starknet_mempool_node::config::MempoolNodeConfig; +use starknet_state_reader::config::RpcStateReaderConfig; use tokio::net::TcpListener; use crate::integration_test_setup::IntegrationTestSetup;