cfxcore/
errors.rs

1// Copyright 2020 Conflux Foundation. All rights reserved.
2// Conflux is free software and distributed under GNU General Public License.
3// See http://www.gnu.org/licenses/
4use crate::light_protocol::Error as LightProtocolError;
5use cfx_rpc_eth_types::Error as EthRpcError;
6pub use cfx_rpc_utils::error::{
7    error_codes::EXCEPTION_ERROR,
8    jsonrpc_error_helpers::error_object_owned_to_jsonrpc_error,
9};
10use cfx_statedb::Error as StateDbError;
11use cfx_storage::Error as StorageError;
12use cfxcore_errors::ProviderBlockError;
13use jsonrpc_core::{futures::future, Error as JsonRpcError, ErrorCode};
14use jsonrpsee::types::ErrorObjectOwned;
15use primitives::{account::AccountError, filter::FilterError};
16use rlp::DecoderError;
17use serde_json::Value;
18use std::{
19    fmt::{Debug, Display},
20    pin::Pin,
21};
22use thiserror::Error;
23
24#[derive(Debug, Error)]
25pub enum Error {
26    #[error(transparent)]
27    FilterError(#[from] FilterError),
28    #[error(transparent)]
29    Storage(#[from] StorageError),
30    #[error(transparent)]
31    StateDb(#[from] StateDbError),
32    #[error(transparent)]
33    Decoder(#[from] DecoderError),
34    #[error(transparent)]
35    LightProtocol(#[from] LightProtocolError),
36    #[error(
37        "JsonRpcError directly constructed to return to Rpc peer. Error: {0}"
38    )]
39    JsonRpcError(#[from] JsonRpcError),
40    #[error(
41        "JsonRpseeError directly constructed to return to Rpc peer. Error: {0}"
42    )]
43    JsonRpseeError(#[from] ErrorObjectOwned),
44    #[error("Jsonrpc error InvalidParam {0}: {1}.")]
45    InvalidParam(String, String),
46    #[error("Custom error detail: {0}")]
47    Custom(String),
48    #[error("Msg error detail: {0}")]
49    Msg(String),
50}
51
52pub type BoxFuture<T> = Pin<Box<dyn future::Future<Output = Result<T>> + Send>>;
53
54pub type Result<T> = std::result::Result<T, Error>;
55
56impl From<Error> for JsonRpcError {
57    fn from(e: Error) -> JsonRpcError {
58        match e {
59            Error::JsonRpcError(j) => j,
60            Error::JsonRpseeError(e) => error_object_owned_to_jsonrpc_error(e),
61            Error::InvalidParam(param, details) => {
62                JsonRpcError {
63                    code: ErrorCode::InvalidParams,
64                    message: format!("Invalid parameters: {}", param),
65                    data: Some(Value::String(format!("{:?}", details))),
66                }
67            }
68            Error::Msg(_)
69            | Error::Decoder(_)
70
71            // TODO(thegaram): consider returning InvalidParams instead
72            | Error::FilterError(_)
73
74            // TODO(thegaram): make error conversion more fine-grained here
75            | Error::LightProtocol(_)
76            | Error::StateDb(_)
77            | Error::Storage(_)
78            | Error::Custom(_) => JsonRpcError {
79                code: ErrorCode::ServerError(EXCEPTION_ERROR),
80                message: format!("Error processing request: {}", e),
81                data: None,
82            },
83        }
84    }
85}
86
87impl From<Error> for ErrorObjectOwned {
88    fn from(e: Error) -> ErrorObjectOwned {
89        let err: JsonRpcError = e.into();
90        ErrorObjectOwned::owned(err.code.code() as i32, err.message, err.data)
91    }
92}
93
94impl From<&str> for Error {
95    fn from(s: &str) -> Error { Error::Msg(s.into()) }
96}
97
98impl From<String> for Error {
99    fn from(s: String) -> Error { Error::Msg(s) }
100}
101
102impl From<ProviderBlockError> for Error {
103    fn from(e: ProviderBlockError) -> Error { Error::from(e.to_string()) }
104}
105
106impl From<EthRpcError> for Error {
107    fn from(e: EthRpcError) -> Error {
108        let e: JsonRpcError = error_object_owned_to_jsonrpc_error(e.into());
109        e.into()
110    }
111}
112
113pub(crate) fn invalid_params<T: Debug>(param: &str, details: T) -> Error {
114    Error::JsonRpcError(JsonRpcError {
115        code: ErrorCode::InvalidParams,
116        message: format!("Invalid parameters: {}", param),
117        data: Some(Value::String(format!("{:?}", details))),
118    })
119    .into()
120}
121
122pub(crate) fn invalid_params_check<T, E: Display>(
123    param: &str, r: std::result::Result<T, E>,
124) -> Result<T> {
125    match r {
126        Ok(t) => Ok(t),
127        Err(e) => {
128            Err(Error::InvalidParam(param.into(), format!("{}", e)).into())
129        }
130    }
131}
132
133pub fn account_result_to_rpc_result<T>(
134    param: &str, result: std::result::Result<T, AccountError>,
135) -> Result<T> {
136    match result {
137        Ok(t) => Ok(t),
138        Err(AccountError::InvalidRlp(decoder_error)) => {
139            Err(decoder_error.into())
140        }
141        Err(e) => Err(invalid_params(param, format!("{}", e))),
142    }
143}