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_gateway_types,starknet_http_server): move spec error conversion to the http server #2904

Merged
merged 1 commit into from
Dec 25, 2024
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
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion crates/starknet_gateway_types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ workspace = true

[dependencies]
async-trait.workspace = true
axum.workspace = true
enum-assoc.workspace = true
mockall = { workspace = true, optional = true }
papyrus_network_types.workspace = true
Expand Down
21 changes: 0 additions & 21 deletions crates/starknet_gateway_types/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use axum::http::StatusCode;
use axum::response::{IntoResponse, Response};
use enum_assoc::Assoc;
use papyrus_network_types::network_types::BroadcastedMessageMetadata;
use papyrus_rpc::error::{
Expand Down Expand Up @@ -59,25 +57,6 @@ pub enum GatewaySpecError {
ValidationFailure { data: String },
}

impl IntoResponse for GatewaySpecError {
fn into_response(self) -> Response {
let as_rpc = self.into_rpc();
// TODO(Arni): Fix the status code. The status code should be a HTTP status code - not a
// Json RPC error code. status code.
let status =
StatusCode::from_u16(u16::try_from(as_rpc.code).expect("Expecting a valid u16"))
.expect("Expecting a valid error code");

let resp = Response::builder()
.status(status)
.body((as_rpc.message, as_rpc.data))
.expect("Expecting valid response");
let status = resp.status();
let body = serde_json::to_string(resp.body()).expect("Expecting valid body");
(status, body).into_response()
}
}

impl std::fmt::Display for GatewaySpecError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let as_rpc = self.clone().into_rpc();
Expand Down
2 changes: 2 additions & 0 deletions crates/starknet_http_server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@ workspace = true
axum.workspace = true
hyper.workspace = true
infra_utils.workspace = true
jsonrpsee = { workspace = true, features = ["full"] }
metrics.workspace = true
papyrus_config.workspace = true
reqwest = { workspace = true, optional = true }
serde.workspace = true
serde_json.workspace = true
starknet_api.workspace = true
starknet_gateway_types.workspace = true
starknet_sequencer_infra.workspace = true
Expand Down
48 changes: 48 additions & 0 deletions crates/starknet_http_server/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,56 @@
use axum::response::{IntoResponse, Response};
use jsonrpsee::types::error::ErrorCode;
use starknet_gateway_types::communication::GatewayClientError;
use starknet_gateway_types::errors::GatewayError;
use thiserror::Error;
use tracing::error;

/// Errors originating from `[`HttpServer::run`]` command.
#[derive(Debug, Error)]
pub enum HttpServerRunError {
#[error(transparent)]
ServerStartupError(#[from] hyper::Error),
}

/// Errors that may occure during the runtime of the HTTP server.
#[derive(Error, Debug)]
pub enum HttpServerError {
#[error(transparent)]
GatewayClientError(#[from] GatewayClientError),
}

impl IntoResponse for HttpServerError {
fn into_response(self) -> Response {
match self {
HttpServerError::GatewayClientError(e) => gw_client_err_into_response(e),
}
}
}

fn gw_client_err_into_response(err: GatewayClientError) -> Response {
let general_rpc_error = match err {
GatewayClientError::ClientError(e) => {
error!("Encountered a ClientError: {}", e);
jsonrpsee::types::ErrorObject::owned(
ErrorCode::InternalError.code(),
"Internal error",
None::<()>,
)
}
GatewayClientError::GatewayError(GatewayError::GatewaySpecError {
source,
p2p_message_metadata: _,
}) => {
// TODO(yair): Find out what is the p2p_message_metadata and whether it needs to be
// added to the error response.
let rpc_spec_error = source.into_rpc();
jsonrpsee::types::ErrorObject::owned(
ErrorCode::ServerError(rpc_spec_error.code).code(),
rpc_spec_error.message,
rpc_spec_error.data,
)
}
};

serde_json::to_vec(&general_rpc_error).expect("Expecting a serializable error.").into_response()
}
16 changes: 7 additions & 9 deletions crates/starknet_http_server/src/http_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,20 @@ use infra_utils::type_name::short_type_name;
use starknet_api::rpc_transaction::RpcTransaction;
use starknet_api::transaction::TransactionHash;
use starknet_gateway_types::communication::SharedGatewayClient;
use starknet_gateway_types::errors::GatewaySpecError;
use starknet_gateway_types::gateway_types::GatewayInput;
use starknet_sequencer_infra::component_definitions::ComponentStarter;
use starknet_sequencer_infra::errors::ComponentError;
use tracing::{error, info, instrument};
use tracing::{debug, info, instrument};

use crate::config::HttpServerConfig;
use crate::errors::HttpServerRunError;
use crate::errors::{HttpServerError, HttpServerRunError};
use crate::metrics::{init_metrics, record_added_transaction, record_added_transaction_status};

#[cfg(test)]
#[path = "http_server_test.rs"]
pub mod http_server_test;

pub type HttpServerResult<T> = Result<T, GatewaySpecError>;
pub type HttpServerResult<T> = Result<T, HttpServerError>;

pub struct HttpServer {
pub config: HttpServerConfig,
Expand Down Expand Up @@ -68,18 +67,17 @@ async fn add_tx(
) -> HttpServerResult<Json<TransactionHash>> {
record_added_transaction();
let gateway_input: GatewayInput = GatewayInput { rpc_tx: tx, message_metadata: None };

let add_tx_result = app_state.gateway_client.add_tx(gateway_input).await.map_err(|join_err| {
error!("Failed to process tx: {}", join_err);
GatewaySpecError::UnexpectedError { data: "Internal server error".to_owned() }
let add_tx_result = app_state.gateway_client.add_tx(gateway_input).await.map_err(|e| {
debug!("Error while adding transaction: {}", e);
HttpServerError::from(e)
});
record_added_transaction_status(add_tx_result.is_ok());

add_tx_result_as_json(add_tx_result)
}

pub(crate) fn add_tx_result_as_json(
result: Result<TransactionHash, GatewaySpecError>,
result: HttpServerResult<TransactionHash>,
) -> HttpServerResult<Json<TransactionHash>> {
let tx_hash = result?;
Ok(Json(tx_hash))
Expand Down
Loading