Skip to main content

nym_bandwidth_controller/
error.rs

1// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
2// SPDX-License-Identifier: Apache-2.0
3
4use nym_credentials::error::Error as CredentialsError;
5use nym_validator_client::{coconut::EcashApiError, nym_api::EpochId};
6use thiserror::Error;
7
8use crate::traits::CredentialFetcherError;
9
10#[derive(Debug, Error)]
11pub enum BandwidthControllerError {
12    #[error("Nyxd error: {0}")]
13    Nyxd(#[from] nym_validator_client::nyxd::error::NyxdError),
14
15    #[error("coconut api query failure: {0}")]
16    CoconutApiError(#[from] EcashApiError),
17
18    #[error("There was a credential storage error - {0}")]
19    CredentialStorageError(Box<dyn std::error::Error + Send + Sync>),
20
21    #[error("a credential/global-data fetcher failed - {0}")]
22    CredentialFetcherError(CredentialFetcherError),
23
24    #[error("No expiration date signatures for epoch : {epoch_id}")]
25    MissingExpirationDateSignatures { epoch_id: EpochId },
26
27    #[error("No coin index signatures for epoch : {epoch_id}")]
28    MissingCoinIndexSignatures { epoch_id: EpochId },
29
30    #[error("No verification key for epoch : {epoch_id}")]
31    MissingVerificationKey { epoch_id: EpochId },
32
33    #[error("No credential fetcher available")]
34    MissingCredentialFetcher,
35
36    #[error("retrieved upgrade mode token is not a valid String")]
37    MalformedUpgradeModeToken,
38
39    #[error("Credential error - {0}")]
40    CredentialError(#[from] CredentialsError),
41
42    // Internal error that should not happen
43    #[error("internal error: {0}")]
44    Internal(String),
45
46    #[error("A channel we were using is closed")]
47    ChannelClosed,
48
49    #[error("Threshold not set yet")]
50    NoThreshold,
51
52    #[error("did not receive a valid response for aggregated data ({typ}) from ANY nym-api")]
53    ExhaustedApiQueries { typ: String },
54
55    #[error("failed to parse ticket type: {0}")]
56    ParseTicketType(String),
57
58    /// A required type has no usable stock and nothing is being fetched for it - as opposed to a
59    /// fetch that actively failed (see [`Self::TicketbookFetchFailed`]).
60    #[error("some required ticketbooks are unavailable and none are being fetched")]
61    TicketbooksUnavailable,
62
63    /// A required type's fetch actively failed; `reason` is the underlying fetcher error as text.
64    #[error("a required ticketbook fetch failed : {reason}")]
65    TicketbookFetchFailed { reason: String },
66}
67
68impl BandwidthControllerError {
69    pub fn credential_storage_error(
70        source: impl std::error::Error + Send + Sync + 'static,
71    ) -> Self {
72        BandwidthControllerError::CredentialStorageError(Box::new(source))
73    }
74
75    pub fn fetcher_error(source: CredentialFetcherError) -> Self {
76        BandwidthControllerError::CredentialFetcherError(source)
77    }
78
79    pub fn internal(message: impl ToString) -> Self {
80        BandwidthControllerError::Internal(message.to_string())
81    }
82}
83
84/// Coarse category of a fetcher error, so the controller can react to specific cases; anything it
85/// doesn't special-case is `Other`.
86#[derive(Debug, Clone, Copy)]
87pub enum FetcherErrorKind {
88    /// the account lacks the funds to make further deposits
89    BandwidthDepleted,
90    /// a nym-api / ecash query failed
91    Api,
92    /// an unexpected failure that shouldn't normally happen
93    Unexpected,
94    /// a local storage failure
95    Storage,
96    /// anything not worth branching on
97    Other,
98}