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