qudag_exchange/
error.rs

1//! Error types for QuDAG Exchange with security-focused error handling
2
3use thiserror::Error;
4use zeroize::{Zeroize, ZeroizeOnDrop};
5
6/// Main error type for the exchange
7#[derive(Error, Debug)]
8pub enum ExchangeError {
9    /// Cryptographic operation failed
10    #[error("Cryptographic error: {0}")]
11    Crypto(#[from] qudag_crypto::CryptoError),
12
13    /// Vault operation failed
14    #[error("Vault error: {0}")]
15    Vault(String),
16
17    /// Network operation failed
18    #[error("Network error: {0}")]
19    Network(String),
20
21    /// DAG consensus error
22    #[error("DAG consensus error: {0}")]
23    Consensus(String),
24
25    /// Zero-knowledge proof verification failed
26    #[error("ZKP verification failed: {0}")]
27    ZkpVerification(String),
28
29    /// Resource metering error
30    #[error("Resource metering error: {0}")]
31    Metering(String),
32
33    /// Transaction validation failed
34    #[error("Transaction validation failed: {0}")]
35    TransactionValidation(String),
36
37    /// Insufficient rUv credits
38    #[error("Insufficient rUv credits: required {required}, available {available}")]
39    InsufficientCredits {
40        /// Required credits
41        required: u64,
42        /// Available credits
43        available: u64,
44    },
45
46    /// Rate limiting exceeded
47    #[error("Rate limit exceeded: {0}")]
48    RateLimitExceeded(String),
49
50    /// Authentication failed
51    #[error("Authentication failed")]
52    AuthenticationFailed,
53
54    /// Authorization failed
55    #[error("Authorization failed: {0}")]
56    AuthorizationFailed(String),
57
58    /// Invalid signature
59    #[error("Invalid signature")]
60    InvalidSignature,
61
62    /// Timing attack detected
63    #[error("Timing anomaly detected - potential attack")]
64    TimingAnomaly,
65
66    /// Replay attack detected
67    #[error("Replay attack detected")]
68    ReplayAttack,
69
70    /// Double spending attempt
71    #[error("Double spending attempt detected")]
72    DoubleSpending,
73
74    /// Resource exhaustion attack
75    #[error("Resource exhaustion detected")]
76    ResourceExhaustion,
77
78    /// Invalid state transition
79    #[error("Invalid state transition: {0}")]
80    InvalidStateTransition(String),
81
82    /// Serialization error
83    #[error("Serialization error: {0}")]
84    Serialization(String),
85
86    /// IO error
87    #[error("IO error: {0}")]
88    Io(#[from] std::io::Error),
89
90    /// Generic error (avoid using when possible)
91    #[error("Exchange error: {0}")]
92    Other(String),
93}
94
95/// Security-sensitive error that may contain secrets
96#[derive(Debug)]
97pub struct SecureError {
98    inner: String,
99}
100
101impl SecureError {
102    /// Create a new secure error
103    pub fn new(msg: String) -> Self {
104        Self { inner: msg }
105    }
106}
107
108impl Drop for SecureError {
109    fn drop(&mut self) {
110        self.inner.zeroize();
111    }
112}
113
114impl std::fmt::Display for SecureError {
115    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
116        write!(f, "[REDACTED]")
117    }
118}
119
120/// Result type alias
121pub type Result<T> = std::result::Result<T, ExchangeError>;
122
123#[cfg(test)]
124mod tests {
125    use super::*;
126
127    #[test]
128    fn test_secure_error_zeroization() {
129        let mut error = SecureError::new("sensitive data".to_string());
130        drop(error);
131        // After drop, the inner string should be zeroized
132    }
133
134    #[test]
135    fn test_secure_error_display() {
136        let error = SecureError::new("sensitive data".to_string());
137        assert_eq!(format!("{}", error), "[REDACTED]");
138    }
139}