diff --git a/client/src/http_sender.rs b/client/src/http_sender.rs index ea79d73338..d72122b3a6 100644 --- a/client/src/http_sender.rs +++ b/client/src/http_sender.rs @@ -27,6 +27,13 @@ impl HttpSender { } } +#[derive(Deserialize, Debug)] +struct RpcErrorObject { + code: i64, + message: String, + /*data field omitted*/ +} + impl RpcSender for HttpSender { fn send(&self, request: RpcRequest, params: serde_json::Value) -> Result { // Concurrent requests are not supported so reuse the same request id for all requests @@ -63,11 +70,20 @@ impl RpcSender for HttpSender { let json: serde_json::Value = serde_json::from_str(&response.text()?)?; if json["error"].is_object() { - return Err(RpcError::RpcRequestError(format!( - "RPC Error response: {}", - serde_json::to_string(&json["error"]).unwrap() - )) - .into()); + return match serde_json::from_value::(json["error"].clone()) + { + Ok(rpc_error_object) => Err(RpcError::RpcResponseError { + code: rpc_error_object.code, + message: rpc_error_object.message, + } + .into()), + Err(err) => Err(RpcError::RpcRequestError(format!( + "Failed to deserialize RPC error response: {} [{}]", + serde_json::to_string(&json["error"]).unwrap(), + err + )) + .into()), + }; } return Ok(json["result"].clone()); } diff --git a/client/src/lib.rs b/client/src/lib.rs index 3d70dd0a1a..7e8cce4acf 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -10,6 +10,7 @@ pub mod perf_utils; pub mod pubsub_client; pub mod rpc_client; pub mod rpc_config; +pub mod rpc_custom_error; pub mod rpc_filter; pub mod rpc_request; pub mod rpc_response; diff --git a/core/src/rpc_error.rs b/client/src/rpc_custom_error.rs similarity index 96% rename from core/src/rpc_error.rs rename to client/src/rpc_custom_error.rs index 6529f661c3..1cd206bbb4 100644 --- a/core/src/rpc_error.rs +++ b/client/src/rpc_custom_error.rs @@ -1,5 +1,7 @@ +//! Implementation defined RPC server errors + +use crate::rpc_response::RpcSimulateTransactionResult; use jsonrpc_core::{Error, ErrorCode}; -use solana_client::rpc_response::RpcSimulateTransactionResult; use solana_sdk::clock::Slot; const JSON_RPC_SERVER_ERROR_1: i64 = -32001; diff --git a/client/src/rpc_request.rs b/client/src/rpc_request.rs index 66e66a61ec..d973c9fac7 100644 --- a/client/src/rpc_request.rs +++ b/client/src/rpc_request.rs @@ -140,8 +140,10 @@ impl RpcRequest { #[derive(Debug, Error)] pub enum RpcError { - #[error("rpc request error: {0}")] + #[error("RPC request error: {0}")] RpcRequestError(String), + #[error("RPC response error {code}: {message}")] + RpcResponseError { code: i64, message: String }, #[error("parse error: expected {0}")] ParseError(String), /* "expected" */ // Anything in a `ForUser` needs to die. The caller should be diff --git a/core/src/lib.rs b/core/src/lib.rs index acbc51854d..61c29d8df7 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -55,7 +55,6 @@ mod result; pub mod retransmit_stage; pub mod rewards_recorder_service; pub mod rpc; -pub mod rpc_error; pub mod rpc_health; pub mod rpc_pubsub; pub mod rpc_pubsub_service; diff --git a/core/src/rpc.rs b/core/src/rpc.rs index 654e03fae2..d74fb2b438 100644 --- a/core/src/rpc.rs +++ b/core/src/rpc.rs @@ -5,7 +5,6 @@ use crate::{ contact_info::ContactInfo, non_circulating_supply::calculate_non_circulating_supply, optimistically_confirmed_bank_tracker::OptimisticallyConfirmedBank, - rpc_error::RpcCustomError, rpc_health::*, send_transaction_service::{SendTransactionService, TransactionInfo}, validator::ValidatorExit, @@ -23,6 +22,7 @@ use solana_account_decoder::{ }; use solana_client::{ rpc_config::*, + rpc_custom_error::RpcCustomError, rpc_filter::{Memcmp, MemcmpEncodedBytes, RpcFilterType}, rpc_request::{ TokenAccountsFilter, DELINQUENT_VALIDATOR_SLOT_DISTANCE, MAX_GET_CONFIRMED_BLOCKS_RANGE,