primitives/errors/
mod.rs

1use serde::{Deserialize, Serialize};
2
3use crate::types::{identifiers::FaultyPeer, PeerIndex};
4
5#[derive(thiserror::Error, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
6pub enum PrimitiveError {
7    // --- Serialization Errors ---
8    #[error("Serialization Failed: {0}.")]
9    SerializationFailed(String),
10    #[error("Deserialization Failed: {0}.")]
11    DeserializationFailed(String),
12
13    // --- Verification Errors (Wrong...) ---
14    #[error("Wrong Opening: Expected {0}, got {1}.")]
15    WrongOpening(String, String),
16    #[error("Wrong Echo from {0}.")]
17    WrongEcho(FaultyPeer),
18    #[error("Wrong signature: {0}.")]
19    WrongSignature(String),
20    #[error("Wrong MAC for {0}. Expected {1:?}, got {2:?}.")]
21    WrongMACFor(FaultyPeer, String, String),
22    #[error("Wrong MAC. Expected {0:?}, got {1:?}.")]
23    WrongMAC(String, String),
24    #[error("Wrong correlation. {0}")]
25    WrongCorrelation(String),
26
27    // --- Validation Errors ---
28    #[error("Invalid Size: expected {0} elements, got {1}")]
29    InvalidSize(usize, usize),
30    #[error("Minimum Length Error: expected at least {0} elements, got {1}")]
31    MinimumLength(usize, usize),
32    #[error("Invalid Parameters: {0}")]
33    InvalidParameters(String),
34    #[error("PeerIndex out of bounds: {0} ∉ [0, {1}].")]
35    InvalidPeerIndex(PeerIndex, usize),
36
37    // --- Other Errors ---
38    #[error("Zero value sampled for type {0}")]
39    ZeroValueSampled(String),
40}
41
42impl From<quinn::rustls::Error> for PrimitiveError {
43    fn from(err: quinn::rustls::Error) -> Self {
44        PrimitiveError::InvalidParameters(err.to_string())
45    }
46}
47
48impl From<Vec<PrimitiveError>> for PrimitiveError {
49    /// Aggregate multiple PrimitiveErrors into one. Only WrongMACFor and WrongEcho can be
50    /// aggregated, and all errors must be of the same type.
51    fn from(errors: Vec<PrimitiveError>) -> Self {
52        if errors.is_empty() {
53            return PrimitiveError::InvalidParameters(
54                "Cannot aggregate an empty list of errors.".to_owned(),
55            );
56        };
57        if errors.len() == 1 {
58            return errors.into_iter().next().unwrap();
59        }
60
61        let (peers, expect, receiver, invalid_errs) = errors.into_iter().fold(
62            (vec![], vec![], vec![], vec![]),
63            |(mut peers, mut expect, mut receiver, mut invalid_errors), e| {
64                match e {
65                    PrimitiveError::WrongMACFor(p, e, r) => {
66                        peers.push(p);
67                        expect.push(e);
68                        receiver.push(r);
69                    }
70                    PrimitiveError::WrongEcho(p) => {
71                        peers.push(p);
72                    }
73                    _ => invalid_errors.push(e.to_string()),
74                }
75                (peers, expect, receiver, invalid_errors)
76            },
77        );
78        if !invalid_errs.is_empty() {
79            return PrimitiveError::InvalidParameters(
80                "Only WrongMACFor|WrongEcho can be aggregated. Got: ".to_owned()
81                    + &invalid_errs.join(", "),
82            );
83        }
84        match (peers, expect.as_slice(), receiver.as_slice()) {
85            (peers, [], []) => PrimitiveError::WrongEcho(FaultyPeer::Multiple(peers)),
86            (peers, expect, receiver) if peers.len() == expect.len() => {
87                PrimitiveError::WrongMACFor(
88                    FaultyPeer::Multiple(peers),
89                    expect.join(", "),
90                    receiver.join(", "),
91                )
92            }
93            _ => PrimitiveError::InvalidParameters(
94                "All errors must be of the same type to be aggregated".to_owned(),
95            ),
96        }
97    }
98}
99impl PrimitiveError {
100    /// Blames another peer for this error.
101    pub(crate) fn blame(self, peer_to_blame: PeerIndex) -> PrimitiveError {
102        match self {
103            PrimitiveError::WrongMAC(expect, receiver) => {
104                PrimitiveError::WrongMACFor(FaultyPeer::Foreign(peer_to_blame), expect, receiver)
105            }
106            PrimitiveError::WrongMACFor(peers, expect, receiver) => {
107                PrimitiveError::WrongMACFor(peers.push(peer_to_blame), expect, receiver)
108            }
109            _ => self,
110        }
111    }
112}