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