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