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