nym_credential_proxy_lib/
error.rs1use nym_crypto::asymmetric::ed25519;
5use nym_ecash_signer_check::SignerCheckError;
6use nym_validator_client::coconut::EcashApiError;
7use nym_validator_client::nym_api::{EpochId, error::NymAPIError};
8use nym_validator_client::nyxd::error::NyxdError;
9use std::io;
10use std::net::SocketAddr;
11use thiserror::Error;
12use time::OffsetDateTime;
13
14#[derive(Debug, Error)]
15pub enum CredentialProxyError {
16 #[error("encountered an internal io error: {source}")]
17 IoError {
18 #[from]
19 source: io::Error,
20 },
21
22 #[error("could not derive valid client url with the provided webhook parameters")]
23 InvalidWebhookUrl,
24
25 #[error("failed to serialise recovery data: {source}")]
26 SerdeJsonFailure {
27 #[from]
28 source: serde_json::Error,
29 },
30
31 #[error("the provided expiration date is too late")]
32 ExpirationDateTooLate,
33
34 #[error("the provided expiration date is too early")]
35 ExpirationDateTooEarly,
36
37 #[error(
38 "failed to bind to {address}: {source}. Are you sure nothing else is running on the specified port and your user has sufficient permission to bind to the requested address?"
39 )]
40 SocketBindFailure {
41 address: SocketAddr,
42 source: io::Error,
43 },
44
45 #[error("the api server failed with the following message: {source}")]
46 HttpServerFailure { source: io::Error },
47
48 #[error("the ecash contract address is not set")]
49 UnavailableEcashContract,
50
51 #[error("the DKG contract address is not set")]
52 UnavailableDKGContract,
53
54 #[error("the bandwidth contract doesn't have any admin set")]
55 MissingBandwidthContractAdmin,
56
57 #[error(
58 "the provided mnemonic does not correspond to the current admin of the bandwidth contract"
59 )]
60 MismatchedMnemonic,
61
62 #[error("failed to interact with the nyx chain: {source}")]
63 NyxdFailure {
64 #[from]
65 source: NyxdError,
66 },
67
68 #[error("validator client error: {0}")]
69 ValidatorClientError(#[from] nym_validator_client::ValidatorClientError),
70
71 #[error("failed to perform ecash operation: {source}")]
72 EcashApiFailure {
73 #[from]
74 source: EcashApiError,
75 },
76
77 #[error("Nym API request failed: {source}")]
78 NymApiFailure { source: Box<NymAPIError> },
79
80 #[error("Compact ecash internal error: {0}")]
81 CompactEcashInternalError(#[from] nym_compact_ecash::error::CompactEcashError),
82
83 #[error("there are no rpc endpoints provided in the environment")]
84 NoNyxEndpointsAvailable,
85
86 #[error("the threshold value for epoch {epoch_id} is not available")]
87 UnavailableThreshold { epoch_id: EpochId },
88
89 #[error(
90 "we have only {available} api clients available while the minimum threshold is {threshold}"
91 )]
92 InsufficientNumberOfSigners { available: usize, threshold: u64 },
93
94 #[error(
95 "we have only managed to obtain {available} partial credentials while the minimum threshold is {threshold}"
96 )]
97 InsufficientNumberOfCredentials { available: usize, threshold: u64 },
98
99 #[error("failed to interact with the credentials: {source}")]
100 CredentialsFailure {
101 #[from]
102 source: nym_credentials::Error,
103 },
104
105 #[error("the DKG has not yet been initialised in the system")]
106 UninitialisedDkg,
107
108 #[error(
109 "credentials can't yet be issued in the system. approximate expected availability: {availability}"
110 )]
111 CredentialsNotYetIssuable { availability: OffsetDateTime },
112
113 #[error("reached seemingly impossible ecash failure")]
114 UnknownEcashFailure,
115
116 #[error("experienced internal database error: {0}")]
117 InternalDatabaseError(#[from] sqlx::Error),
118
119 #[error("experienced internal storage error: {reason}")]
120 DatabaseInconsistency { reason: String },
121
122 #[error("failed to perform startup SQL migration: {0}")]
123 StartupMigrationFailure(#[from] sqlx::migrate::MigrateError),
124
125 #[error("timed out while attempting to obtain partial wallet from {client_repr}")]
126 EcashApiRequestTimeout { client_repr: String },
127
128 #[error("failed to create deposit")]
129 DepositFailure,
130
131 #[error("failed to load jwt signing key from {path}: {err}")]
132 JWTSigningKeyLoadFailure {
133 path: String,
134 #[source]
135 err: std::io::Error,
136 },
137
138 #[error("can't obtain sufficient number of credential shares due to unavailable quorum")]
139 UnavailableSigningQuorum,
140
141 #[error("failed to perform quorum check: {source}")]
142 QuorumCheckFailure {
143 #[from]
144 source: SignerCheckError,
145 },
146
147 #[error(
148 "this operation couldn't be completed as the program is in the process of shutting down"
149 )]
150 ShutdownInProgress,
151
152 #[error("failed to obtain wallet shares with id {id}: {message}")]
153 ShareByIdLoadError { message: String, id: i64 },
154
155 #[error(
156 "failed to obtain wallet shares with device_id {device_id} and credential_id: {credential_id}: {message}"
157 )]
158 ShareByDeviceLoadError {
159 message: String,
160 device_id: String,
161 credential_id: String,
162 },
163
164 #[error("could not find shares with id {id}")]
165 SharesByIdNotFound { id: i64 },
166
167 #[error("could not find shares with device_id {device_id} and credential_id: {credential_id}")]
168 SharesByDeviceNotFound {
169 device_id: String,
170 credential_id: String,
171 },
172
173 #[error(
174 "the attestation check url has not been provided through either the CLI nor the default .env config"
175 )]
176 AttestationCheckUrlNotSet,
177
178 #[error("the provided attester public key is malformed: {source}")]
179 MalformedAttestationCheckUrl { source: url::ParseError },
180
181 #[error(
182 "the attester public key has not been provided through either the CLI nor the default .env config"
183 )]
184 AttesterPublicKeyNotSet,
185
186 #[error("the provided attester public key is malformed: {source}")]
187 MalformedAttesterPublicKey {
188 source: ed25519::Ed25519RecoveryError,
189 },
190}
191
192impl From<NymAPIError> for CredentialProxyError {
193 fn from(source: NymAPIError) -> Self {
194 CredentialProxyError::NymApiFailure {
195 source: Box::new(source),
196 }
197 }
198}
199
200impl CredentialProxyError {
201 pub fn database_inconsistency<S: Into<String>>(reason: S) -> CredentialProxyError {
202 CredentialProxyError::DatabaseInconsistency {
203 reason: reason.into(),
204 }
205 }
206}