1use std::fmt::{self, Display};
5
6use crate::rpc::eth::errors::EthErrors;
7use jsonrpsee::{
8 core::ClientError,
9 types::error::{self, ErrorCode, ErrorObjectOwned},
10};
11
12pub trait RpcErrorData {
14 fn error_code(&self) -> Option<i32> {
16 None
17 }
18
19 fn error_message(&self) -> Option<String> {
21 None
22 }
23
24 fn error_data(&self) -> Option<serde_json::Value> {
26 None
27 }
28}
29
30#[derive(derive_more::From, derive_more::Into, Debug, PartialEq)]
33pub struct ServerError {
34 inner: ErrorObjectOwned,
35}
36
37pub(crate) mod implementation_defined_errors {
41 pub(crate) const UNSUPPORTED_METHOD: i32 = -32001;
45}
46
47impl ServerError {
48 pub fn new(
49 code: i32,
50 message: impl Display,
51 data: impl Into<Option<serde_json::Value>>,
52 ) -> Self {
53 Self {
54 inner: ErrorObjectOwned::owned(code, message.to_string(), data.into()),
55 }
56 }
57 pub fn message(&self) -> &str {
58 self.inner.message()
59 }
60 pub fn known_code(&self) -> ErrorCode {
61 self.inner.code().into()
62 }
63 pub fn stubbed_for_openrpc() -> Self {
66 Self::new(
67 4528,
68 "unimplemented",
69 Some(
70 "This method is stubbed as part of https://github.com/ChainSafe/forest/issues/4528"
71 .into(),
72 ),
73 )
74 }
75
76 pub fn unsupported_method() -> Self {
77 Self::new(
78 implementation_defined_errors::UNSUPPORTED_METHOD,
79 "unsupported method",
80 Some("This method is not supported by the current version of the Forest node".into()),
81 )
82 }
83
84 pub fn inner(&self) -> &ErrorObjectOwned {
85 &self.inner
86 }
87}
88
89impl<E: std::error::Error + RpcErrorData + 'static> From<E> for ServerError {
90 fn from(error: E) -> Self {
91 let code = error.error_code().unwrap_or(error::INTERNAL_ERROR_CODE);
92 let message = error.error_message().unwrap_or_else(|| error.to_string());
93 let data = error.error_data();
94
95 Self::new(code, message, data)
96 }
97}
98
99impl From<anyhow::Error> for ServerError {
101 fn from(error: anyhow::Error) -> Self {
102 if let Some(eth_error) = error.downcast_ref::<EthErrors>() {
104 return eth_error.clone().into();
105 }
106
107 Self::internal_error(error.to_string(), None)
109 }
110}
111
112impl Display for ServerError {
113 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
114 f.write_str("JSON-RPC error:\n")?;
115 f.write_fmt(format_args!("\tcode: {}\n", self.inner.code()))?;
116 f.write_fmt(format_args!("\tmessage: {}\n", self.inner.message()))?;
117 if let Some(data) = self.inner.data() {
118 f.write_fmt(format_args!("\tdata: {data}\n"))?
119 }
120 Ok(())
121 }
122}
123
124impl std::error::Error for ServerError {}
125
126macro_rules! ctor {
127 ($($ctor:ident { $code:expr })*) => {
128 $(
129 impl ServerError {
130 pub fn $ctor(message: impl Display, data: impl Into<Option<serde_json::Value>>) -> Self {
131 Self::new($code, message, data)
132 }
133 }
134 )*
135 }
136}
137
138ctor! {
139 parse_error { error::PARSE_ERROR_CODE }
140 internal_error { error::INTERNAL_ERROR_CODE }
141 invalid_params { error::INVALID_PARAMS_CODE }
142 method_not_found { error::METHOD_NOT_FOUND_CODE }
143}
144
145macro_rules! from2internal {
146 ($($ty:ty),* $(,)?) => {
147 $(
148 impl From<$ty> for ServerError {
149 fn from(it: $ty) -> Self {
150 Self::internal_error(it, None)
151 }
152 }
153 )*
154 };
155}
156
157from2internal! {
158 String,
159 base64::DecodeError,
160 cid::multibase::Error,
161 crate::chain::store::Error,
162 crate::chain_sync::TipsetValidationError,
163 crate::key_management::Error,
164 crate::libp2p::ParseError,
165 crate::message_pool::Error,
166 crate::state_manager::Error,
167 fil_actors_shared::fvm_ipld_amt::Error,
168 futures::channel::oneshot::Canceled,
169 fvm_ipld_encoding::Error,
170 fvm_shared4::address::Error,
171 jsonwebtoken::errors::Error,
172 std::io::Error,
173 std::time::SystemTimeError,
174 tokio::task::JoinError,
175 fil_actors_shared::fvm_ipld_hamt::Error,
176 flume::RecvError,
177 fil_actors_shared::v12::ActorError,
178 fil_actors_shared::v13::ActorError,
179 fil_actors_shared::v14::ActorError,
180 fil_actors_shared::v15::ActorError,
181 fil_actors_shared::v16::ActorError,
182 serde_json::Error,
183 jsonrpsee::core::client::error::Error,
184}
185
186impl From<ServerError> for ClientError {
187 fn from(value: ServerError) -> Self {
188 Self::Call(value.inner)
189 }
190}
191
192impl<T> From<flume::SendError<T>> for ServerError {
193 fn from(e: flume::SendError<T>) -> Self {
194 Self::internal_error(e, None)
195 }
196}
197
198impl<T> From<tokio::sync::mpsc::error::SendError<T>> for ServerError {
199 fn from(e: tokio::sync::mpsc::error::SendError<T>) -> Self {
200 Self::internal_error(e, None)
201 }
202}