use std::fmt;
use std::io;
use std::time::Duration;
use thiserror::Error;
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug, Error)]
pub enum Error {
#[error("Cryptographic error: {0}")]
Crypto(#[from] CryptoError),
#[error("Consensus error: {0}")]
Consensus(#[from] ConsensusError),
#[error("Agent error: {0}")]
Agent(#[from] AgentError),
#[error("Validation error: {0}")]
Validation(#[from] ValidationError),
#[error("System error: {0}")]
System(#[from] SystemError),
#[error("Network error: {0}")]
Network(#[from] NetworkError),
#[error("I/O error: {0}")]
Io(#[from] io::Error),
#[error("Serialization error: {0}")]
Serialization(#[from] SerializationError),
#[error("Operation timed out after {duration:?}: {operation}")]
Timeout {
operation: String,
duration: Duration,
},
#[error("{message}")]
Other {
message: String,
#[source]
source: Option<Box<dyn std::error::Error + Send + Sync>>,
},
#[error("Key not found: {0}")]
KeyNotFound(String),
#[error("Configuration error: {0}")]
Configuration(String),
#[error("Task join error: {0}")]
TaskJoin(String),
#[error("Agent pool exhausted")]
PoolExhausted,
#[error("Config error: {0}")]
Config(String),
#[error("DID error: {0}")]
Did(String),
#[error("Invalid state: {message}")]
InvalidState {
message: String,
},
#[error("Authority not found: {authority}")]
AuthorityNotFound {
authority: String,
},
#[error("Invalid vote from {authority}: {reason}")]
InvalidVote {
authority: String,
reason: String,
},
#[error("Duplicate vote from {authority}")]
DuplicateVote {
authority: String,
},
#[error("Byzantine fault: {message}")]
ByzantineFault {
message: String,
},
#[error("View change required: {0}")]
ViewChangeRequired(String),
#[error("Consensus already reached")]
AlreadyReached,
}
#[derive(Debug, Error)]
pub enum CryptoError {
#[error("Signature verification failed: {reason}")]
SignatureVerificationFailed {
reason: String,
public_key: Option<String>,
},
#[error("Invalid signature format: {details}")]
InvalidSignature {
details: String,
},
#[error("Invalid public key: {details}")]
InvalidPublicKey {
details: String,
},
#[error("Invalid private key: {details}")]
InvalidPrivateKey {
details: String,
},
#[error("Key generation failed: {reason}")]
KeyGenerationFailed {
reason: String,
},
#[error("Key derivation failed: {reason}")]
KeyDerivationFailed {
reason: String,
},
#[error("PKCS#8 error: {details}")]
Pkcs8Error {
details: String,
},
#[error("Hash computation failed: {algorithm}")]
HashError {
algorithm: String,
},
#[error("Random number generation failed: {reason}")]
RandomGenerationFailed {
reason: String,
},
#[error("Batch verification failed: {passed}/{total} signatures valid")]
BatchVerificationFailed {
passed: usize,
total: usize,
},
#[error("HSM operation failed: {operation}")]
HsmError {
operation: String,
},
}
#[derive(Debug, Error)]
pub enum ConsensusError {
#[error("Consensus not reached: {votes_for}/{total_votes} votes (required {required})")]
ConsensusNotReached {
votes_for: usize,
total_votes: usize,
required: usize,
},
#[error("Quorum not achieved: {available}/{required} agents available")]
QuorumNotAchieved {
available: usize,
required: usize,
},
#[error("BFT voting round {round} failed: {reason}")]
VotingRoundFailed {
round: u64,
reason: String,
},
#[error("Byzantine agent detected: {agent_id} - {behavior}")]
ByzantineAgentDetected {
agent_id: String,
behavior: String,
},
#[error("Invalid vote from agent {agent_id}: {reason}")]
InvalidVote {
agent_id: String,
reason: String,
},
#[error("Consensus timeout after {duration:?} with {votes_cast}/{total_agents} votes")]
ConsensusTimeout {
duration: Duration,
votes_cast: usize,
total_agents: usize,
},
#[error("Pool size {size} too small for BFT (minimum {minimum} required)")]
InsufficientPoolSize {
size: usize,
minimum: usize,
},
#[error("Conflicting consensus results: {count} different outcomes")]
ConflictingResults {
count: usize,
},
#[error("Invalid consensus state: {0}")]
InvalidState(String),
#[error("Authority not found: {0}")]
AuthorityNotFound(String),
#[error("Duplicate vote from authority: {0}")]
DuplicateVote(String),
#[error("Byzantine fault detected: {0}")]
ByzantineFault(String),
#[error("View change required: {0}")]
ViewChangeRequired(String),
#[error("Consensus already reached")]
AlreadyReached,
}
#[derive(Debug, Error)]
pub enum AgentError {
#[error("Failed to spawn agent {agent_type}: {reason}")]
SpawnFailed {
agent_type: String,
reason: String,
},
#[error("Agent not found: {agent_id}")]
AgentNotFound {
agent_id: String,
},
#[error("Agent {agent_id} communication timeout after {duration:?}")]
CommunicationTimeout {
agent_id: String,
duration: Duration,
},
#[error("Agent {agent_id} crashed: {reason}")]
AgentCrashed {
agent_id: String,
reason: String,
},
#[error("Failed to recover agent {agent_id}: {reason}")]
RecoveryFailed {
agent_id: String,
reason: String,
},
#[error("Agent pool exhausted: {active}/{maximum} agents, cannot spawn more")]
PoolExhausted {
active: usize,
maximum: usize,
},
#[error("Invalid state transition for agent {agent_id}: {from} -> {to}")]
InvalidStateTransition {
agent_id: String,
from: String,
to: String,
},
#[error("Agent {agent_id} task execution failed: {task}")]
TaskExecutionFailed {
agent_id: String,
task: String,
details: Option<String>,
},
#[error("Communication error between {from_agent} and {to_agent}: {reason}")]
InterAgentCommunicationFailed {
from_agent: String,
to_agent: String,
reason: String,
},
#[error("Agent pool error: {reason}")]
AgentPoolError {
reason: String,
},
#[error("Health check failed: {reason}")]
HealthCheckFailed {
reason: String,
},
}
#[derive(Debug, Error)]
pub enum ValidationError {
#[error("Trust chain validation failed: {reason}")]
TrustChainInvalid {
reason: String,
depth: Option<usize>,
},
#[error("Certificate not found: {cert_id}")]
CertificateNotFound {
cert_id: String,
},
#[error("Certificate expired: {cert_id} (expired at {expired_at})")]
CertificateExpired {
cert_id: String,
expired_at: String,
},
#[error("Certificate revoked: {cert_id} (reason: {reason})")]
CertificateRevoked {
cert_id: String,
reason: String,
},
#[error("Untrusted certificate issuer: {issuer}")]
UntrustedIssuer {
issuer: String,
},
#[error("Certificate chain too long: {length} (maximum {maximum})")]
ChainTooLong {
length: usize,
maximum: usize,
},
#[error("Invalid certificate format: {details}")]
InvalidCertificateFormat {
details: String,
},
#[error("Verifiable Credential validation failed: {reason}")]
CredentialValidationFailed {
reason: String,
},
#[error("DID resolution failed: {did}")]
DidResolutionFailed {
did: String,
},
#[error("Mandate validation failed: {reason}")]
MandateValidationFailed {
reason: String,
},
#[error("Invalid proof: {details}")]
InvalidProof {
details: String,
},
}
#[derive(Debug, Error)]
pub enum SystemError {
#[error("System initialization failed: {reason}")]
InitializationFailed {
reason: String,
},
#[error("Invalid configuration: {parameter} = {value}")]
InvalidConfiguration {
parameter: String,
value: String,
expected: Option<String>,
},
#[error("Resource allocation failed: {resource}")]
ResourceAllocationFailed {
resource: String,
details: Option<String>,
},
#[error("System not initialized: {component}")]
NotInitialized {
component: String,
},
#[error("System already initialized: {component}")]
AlreadyInitialized {
component: String,
},
#[error("Shutdown failed: {reason}")]
ShutdownFailed {
reason: String,
},
#[error("Database error: {operation}")]
DatabaseError {
operation: String,
details: Option<String>,
},
#[error("Metrics error: {reason}")]
MetricsError {
reason: String,
},
#[error("Thread pool error: {reason}")]
ThreadPoolError {
reason: String,
},
}
#[derive(Debug, Error)]
pub enum NetworkError {
#[error("Connection failed to {endpoint}: {reason}")]
ConnectionFailed {
endpoint: String,
reason: String,
},
#[error("Connection timeout to {endpoint} after {duration:?}")]
ConnectionTimeout {
endpoint: String,
duration: Duration,
},
#[error("Network partition detected: {details}")]
NetworkPartition {
details: String,
},
#[error("Failed to send message to {recipient}: {reason}")]
SendFailed {
recipient: String,
reason: String,
},
#[error("Failed to receive message from {sender}: {reason}")]
ReceiveFailed {
sender: String,
reason: String,
},
#[error("Protocol error: {protocol} - {details}")]
ProtocolError {
protocol: String,
details: String,
},
#[error("Peer disconnected: {peer_id}")]
PeerDisconnected {
peer_id: String,
},
#[error("Invalid network address: {address}")]
InvalidAddress {
address: String,
},
}
#[derive(Debug, Error)]
pub enum SerializationError {
#[error("JSON serialization error: {0}")]
Json(#[from] serde_json::Error),
#[error("Base64 error: {details}")]
Base64 {
details: String,
},
#[error("Invalid data format: expected {expected}, got {actual}")]
InvalidFormat {
expected: String,
actual: String,
},
#[error("Data corruption detected: {details}")]
DataCorruption {
details: String,
},
}
impl From<ed25519_dalek::SignatureError> for Error {
fn from(err: ed25519_dalek::SignatureError) -> Self {
Error::Crypto(CryptoError::SignatureVerificationFailed {
reason: err.to_string(),
public_key: None,
})
}
}
impl From<pkcs8::Error> for Error {
fn from(err: pkcs8::Error) -> Self {
Error::Crypto(CryptoError::Pkcs8Error {
details: err.to_string(),
})
}
}
impl From<base64::DecodeError> for Error {
fn from(err: base64::DecodeError) -> Self {
Error::Serialization(SerializationError::Base64 {
details: err.to_string(),
})
}
}
impl From<uuid::Error> for Error {
fn from(err: uuid::Error) -> Self {
Error::Serialization(SerializationError::InvalidFormat {
expected: "valid UUID".to_string(),
actual: err.to_string(),
})
}
}
impl Error {
pub fn timeout(operation: impl Into<String>, duration: Duration) -> Self {
Self::Timeout {
operation: operation.into(),
duration,
}
}
pub fn other(message: impl Into<String>) -> Self {
Self::Other {
message: message.into(),
source: None,
}
}
pub fn with_source(
message: impl Into<String>,
source: impl std::error::Error + Send + Sync + 'static,
) -> Self {
Self::Other {
message: message.into(),
source: Some(Box::new(source)),
}
}
pub fn agent_pool(message: impl Into<String>) -> Self {
Self::Agent(AgentError::AgentPoolError {
reason: message.into(),
})
}
pub fn config(message: impl Into<String>) -> Self {
Self::Configuration(message.into())
}
pub fn verification(message: impl Into<String>) -> Self {
Self::Crypto(CryptoError::SignatureVerificationFailed {
reason: message.into(),
public_key: None,
})
}
pub fn health_check(message: impl Into<String>) -> Self {
Self::Agent(AgentError::HealthCheckFailed {
reason: message.into(),
})
}
}
impl CryptoError {
pub fn signature_failed(reason: impl Into<String>) -> Self {
Self::SignatureVerificationFailed {
reason: reason.into(),
public_key: None,
}
}
pub fn signature_failed_with_key(reason: impl Into<String>, public_key: impl Into<String>) -> Self {
Self::SignatureVerificationFailed {
reason: reason.into(),
public_key: Some(public_key.into()),
}
}
}
impl ConsensusError {
pub fn not_reached(votes_for: usize, total_votes: usize, required: usize) -> Self {
Self::ConsensusNotReached {
votes_for,
total_votes,
required,
}
}
pub fn no_quorum(available: usize, required: usize) -> Self {
Self::QuorumNotAchieved { available, required }
}
}
impl AgentError {
pub fn spawn_failed(agent_type: impl Into<String>, reason: impl Into<String>) -> Self {
Self::SpawnFailed {
agent_type: agent_type.into(),
reason: reason.into(),
}
}
pub fn not_found(agent_id: impl Into<String>) -> Self {
Self::AgentNotFound {
agent_id: agent_id.into(),
}
}
}
impl ValidationError {
pub fn trust_chain_invalid(reason: impl Into<String>) -> Self {
Self::TrustChainInvalid {
reason: reason.into(),
depth: None,
}
}
pub fn certificate_expired(cert_id: impl Into<String>, expired_at: impl Into<String>) -> Self {
Self::CertificateExpired {
cert_id: cert_id.into(),
expired_at: expired_at.into(),
}
}
}
impl SystemError {
pub fn init_failed(reason: impl Into<String>) -> Self {
Self::InitializationFailed {
reason: reason.into(),
}
}
pub fn invalid_config(parameter: impl Into<String>, value: impl Into<String>) -> Self {
Self::InvalidConfiguration {
parameter: parameter.into(),
value: value.into(),
expected: None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_error_display() {
let err = Error::Crypto(CryptoError::SignatureVerificationFailed {
reason: "invalid signature".to_string(),
public_key: Some("abc123".to_string()),
});
assert!(err.to_string().contains("Cryptographic error"));
assert!(err.to_string().contains("Signature verification failed"));
}
#[test]
fn test_consensus_error_display() {
let err = ConsensusError::not_reached(3, 5, 4);
assert!(err.to_string().contains("3/5"));
assert!(err.to_string().contains("required 4"));
}
#[test]
fn test_error_helper_methods() {
let err = Error::timeout("verification", Duration::from_secs(5));
assert!(matches!(err, Error::Timeout { .. }));
let err = Error::other("something went wrong");
assert!(matches!(err, Error::Other { .. }));
}
#[test]
fn test_crypto_error_helper() {
let err = CryptoError::signature_failed("bad sig");
assert!(matches!(err, CryptoError::SignatureVerificationFailed { .. }));
}
#[test]
fn test_agent_error_helper() {
let err = AgentError::spawn_failed("verifier", "out of memory");
assert!(matches!(err, AgentError::SpawnFailed { .. }));
}
#[test]
fn test_error_source_chain() {
let io_err = io::Error::new(io::ErrorKind::NotFound, "file not found");
let err: Error = io_err.into();
assert!(matches!(err, Error::Io(_)));
}
#[test]
fn test_serialization_error_from_json() {
let json_str = "{invalid json}";
let json_err = serde_json::from_str::<serde_json::Value>(json_str).unwrap_err();
let ser_err: SerializationError = json_err.into();
let err: Error = ser_err.into();
assert!(matches!(err, Error::Serialization(SerializationError::Json(_))));
}
}