1use crate::client::mix_traffic::transceiver::ErasedGatewayError;
5use nym_crypto::asymmetric::ed25519::Ed25519RecoveryError;
6use nym_gateway_client::error::GatewayClientError;
7use nym_task::RegistryAccessError;
8use nym_topology::node::RoutingNodeError;
9use nym_topology::{NodeId, NymTopologyError};
10use nym_validator_client::nym_api::error::NymAPIError;
11use nym_validator_client::nyxd::error::NyxdError;
12use nym_validator_client::ValidatorClientError;
13use rand::distributions::WeightedError;
14use std::error::Error;
15use std::path::PathBuf;
16
17#[derive(thiserror::Error, Debug)]
18pub enum ClientCoreError {
19 #[error("could not perform the state migration: {0}")]
20 UnsupportedMigration(String),
21
22 #[error("I/O error: {0}")]
23 IoError(#[from] std::io::Error),
24
25 #[error("gateway client error ({gateway_id}): {source}")]
26 GatewayClientError {
27 gateway_id: String,
28 source: Box<GatewayClientError>,
29 },
30
31 #[error("custom gateway client error: {source}")]
32 ErasedGatewayClientError {
33 #[from]
34 source: ErasedGatewayError,
35 },
36
37 #[error("ed25519 error: {0}")]
38 Ed25519RecoveryError(#[from] Ed25519RecoveryError),
39
40 #[error("validator client error: {0}")]
41 ValidatorClientError(#[from] ValidatorClientError),
42
43 #[error("no gateway with id: {0}")]
44 NoGatewayWithId(String),
45
46 #[error("Invalid URL: {0}")]
47 InvalidUrl(String),
48
49 #[error("node doesn't advertise ip addresses : {0}")]
50 MissingIpAddress(String),
51
52 #[cfg(not(target_arch = "wasm32"))]
53 #[error("resolution failed: {0}")]
54 ResolutionFailed(#[from] nym_http_api_client::ResolveError),
55
56 #[error("no gateways on network")]
57 NoGatewaysOnNetwork,
58
59 #[error("there are no more new gateways on the network - it seems this client has already registered with all nodes it could have")]
60 NoNewGatewaysAvailable,
61
62 #[error("list of nym apis is empty")]
63 ListOfNymApisIsEmpty,
64
65 #[error("failed to resolve a query to nym API: {source}")]
66 NymApiQueryFailure { source: Box<NymAPIError> },
67
68 #[error(
69 "the current network topology seem to be insufficient to route any packets through:\n\t{0}"
70 )]
71 InsufficientNetworkTopology(#[from] NymTopologyError),
72
73 #[error("experienced a failure with our reply surb persistent storage: {source}")]
74 SurbStorageError {
75 source: Box<dyn Error + Send + Sync>,
76 },
77
78 #[error("experienced a failure with our cryptographic keys persistent storage: {source}")]
79 KeyStoreError {
80 source: Box<dyn Error + Send + Sync>,
81 },
82
83 #[error("experienced a failure with our gateways details storage: {source}")]
84 GatewaysDetailsStoreError {
85 source: Box<dyn Error + Send + Sync>,
86 },
87
88 #[error("experienced a failure with our credentials storage: {source}")]
89 CredentialStoreError {
90 source: Box<dyn Error + Send + Sync>,
91 },
92
93 #[error("the provided ticket type is invalid")]
94 UnknownTicketType,
95
96 #[error("the gateway id is invalid - {0}")]
97 UnableToCreatePublicKeyFromGatewayId(Ed25519RecoveryError),
98
99 #[error("the node is malformed: {source}")]
100 MalformedGateway {
101 #[from]
102 source: Box<RoutingNodeError>,
103 },
104
105 #[error("failed to establish connection to gateway: {source}")]
106 GatewayConnectionFailure { source: Box<tungstenite::Error> },
107
108 #[cfg(target_arch = "wasm32")]
109 #[error("failed to establish gateway connection (wasm)")]
110 GatewayJsConnectionFailure,
111
112 #[error("gateway connection was abruptly closed")]
113 GatewayConnectionAbruptlyClosed,
114
115 #[error("timed out while trying to establish gateway connection")]
116 GatewayConnectionTimeout,
117
118 #[error("failed to forward mix messages to gateway")]
119 GatewayFailedToForwardMessages,
120
121 #[error("no ping measurements for the gateway ({identity}) performed")]
122 NoGatewayMeasurements { identity: String },
123
124 #[error("failed to register receiver for reconstructed mixnet messages")]
125 FailedToRegisterReceiver,
126
127 #[error("unexpected exit")]
128 UnexpectedExit,
129
130 #[error("this operation would have resulted in the gateway {gateway_id:?} key being overwritten without permission")]
131 ForbiddenGatewayKeyOverwrite { gateway_id: String },
132
133 #[error(
134 "this operation would have resulted in clients keys being overwritten without permission"
135 )]
136 ForbiddenKeyOverwrite,
137
138 #[error("the client doesn't have any gateway set as active")]
139 NoActiveGatewaySet,
140
141 #[error("gateway details for gateway {gateway_id:?} are unavailable")]
142 UnavailableGatewayDetails {
143 gateway_id: String,
144 #[source]
145 source: Box<dyn Error + Send + Sync>,
146 },
147
148 #[error("gateway shared key is unavailable whilst we have full node information")]
149 UnavailableSharedKey,
150
151 #[error("attempted to obtain fresh gateway details whilst already knowing about one")]
152 UnexpectedGatewayDetails,
153
154 #[error("the provided gateway details (for gateway {gateway_id}) do not correspond to the shared keys")]
155 MismatchedGatewayDetails { gateway_id: String },
156
157 #[error("unable to upgrade config file from `{current_version}`")]
158 ConfigFileUpgradeFailure { current_version: String },
159
160 #[error("unable to upgrade config file to `{new_version}`")]
161 UnableToUpgradeConfigFile { new_version: String },
162
163 #[error("failed to upgrade config file: {message}")]
164 UpgradeFailure { message: String },
165
166 #[error("the provided gateway details don't much the stored data")]
167 MismatchedStoredGatewayDetails,
168
169 #[error("custom selection of gateway was expected")]
170 CustomGatewaySelectionExpected,
171
172 #[error("custom selection of gateway was unexpected")]
173 UnexpectedCustomGatewaySelection,
174
175 #[error("the persisted gateway details were set for a custom setup")]
176 UnexpectedPersistedCustomGatewayDetails,
177
178 #[error("this client has performed gateway initialisation in another session")]
179 NoInitClientPresent,
180
181 #[error("there are no gateways supporting the wss protocol available")]
182 NoWssGateways,
183
184 #[error("the specified gateway '{gateway}' does not support the wss protocol")]
185 UnsupportedWssProtocol { gateway: String },
186
187 #[error("node {id} ({identity}) does not support mixnet entry mode")]
188 UnsupportedEntry { id: NodeId, identity: String },
189
190 #[error(
191 "failed to load custom topology using path '{}'. detailed message: {source}", file_path.display()
192 )]
193 CustomTopologyLoadFailure {
194 file_path: PathBuf,
195 #[source]
196 source: std::io::Error,
197 },
198
199 #[error(
200 "failed to save config file for client-{typ} id {id} using path '{}'. detailed message: {source}", path.display()
201 )]
202 ConfigSaveFailure {
203 typ: String,
204 id: String,
205 path: PathBuf,
206 #[source]
207 source: std::io::Error,
208 },
209
210 #[error("the provided gateway identity {gateway_id} is malformed: {source}")]
211 MalformedGatewayIdentity {
212 gateway_id: String,
213
214 #[source]
215 source: Ed25519RecoveryError,
216 },
217
218 #[error(
219 "the listening address of gateway {gateway_id} ({raw_listener}) is malformed: {source}"
220 )]
221 MalformedListener {
222 gateway_id: String,
223
224 raw_listener: String,
225
226 #[source]
227 source: url::ParseError,
228 },
229
230 #[error("this client (id: '{client_id}') has already been initialised before. If you want to add additional gateway, use `add-gateway` command")]
231 AlreadyInitialised { client_id: String },
232
233 #[error("this client has already registered with gateway {gateway_id}")]
234 AlreadyRegistered { gateway_id: String },
235
236 #[error(
237 "fresh registration with gateway {gateway_id} somehow requires an additional key upgrade!"
238 )]
239 UnexpectedKeyUpgrade { gateway_id: String },
240
241 #[error("failed to derive keys from master key")]
242 HkdfDerivationError,
243
244 #[error("missing url for constructing RPC client")]
245 RpcClientMissingUrl,
246
247 #[error("provided nym network details were malformed: {source}")]
248 InvalidNetworkDetails { source: NyxdError },
249
250 #[error("failed to construct RPC client: {source}")]
251 RpcClientCreationFailure { source: NyxdError },
252
253 #[error("failed to select valid gateway due to incomputable latency")]
254 GatewaySelectionFailure { source: WeightedError },
255
256 #[error("Could not access task registry, {0}")]
257 RegistryAccess(#[from] RegistryAccessError),
258}
259
260impl From<tungstenite::Error> for ClientCoreError {
261 fn from(err: tungstenite::Error) -> ClientCoreError {
262 ClientCoreError::GatewayConnectionFailure {
263 source: Box::new(err),
264 }
265 }
266}
267
268impl From<NymAPIError> for ClientCoreError {
269 fn from(err: NymAPIError) -> ClientCoreError {
270 ClientCoreError::NymApiQueryFailure {
271 source: Box::new(err),
272 }
273 }
274}
275
276#[derive(Debug)]
278pub enum ClientCoreStatusMessage {
279 GatewayIsSlow,
280 GatewayIsVerySlow,
281}
282
283impl std::fmt::Display for ClientCoreStatusMessage {
284 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
285 match self {
286 ClientCoreStatusMessage::GatewayIsSlow => write!(
287 f,
288 "The connected gateway is slow, or the connection to it is slow"
289 ),
290 ClientCoreStatusMessage::GatewayIsVerySlow => write!(
291 f,
292 "The connected gateway is very slow, or the connection to it is very slow"
293 ),
294 }
295 }
296}
297
298impl nym_task::TaskStatusEvent for ClientCoreStatusMessage {
299 fn as_any(&self) -> &dyn std::any::Any {
300 self
301 }
302}