hopr_crypto_packet/
errors.rs1use std::fmt::Debug;
2
3use hopr_types::{
4 crypto::{errors::CryptoError, prelude::SimplePseudonym},
5 internal::{
6 errors::CoreTypesError,
7 prelude::{ChannelId, Ticket, WinningProbability},
8 },
9 primitive::{
10 errors::GeneralError,
11 prelude::{Address, HoprBalance},
12 },
13};
14use thiserror::Error;
15
16#[derive(Error, Debug)]
17pub enum PacketError {
18 #[error("failed to decode packet: {0}")]
19 PacketDecodingError(String),
20
21 #[error("failed to construct packet: {0}")]
22 PacketConstructionError(String),
23
24 #[error("Proof of Relay challenge could not be verified")]
25 PoRVerificationError,
26
27 #[error("logic error during packet processing: {0}")]
28 LogicError(String),
29
30 #[error("underlying transport error while sending packet: {0}")]
31 TransportError(String),
32
33 #[error(transparent)]
34 CryptographicError(#[from] CryptoError),
35
36 #[error(transparent)]
37 CoreTypesError(#[from] CoreTypesError),
38
39 #[error(transparent)]
40 SphinxError(#[from] crate::sphinx::errors::SphinxError),
41
42 #[error(transparent)]
43 PixError(#[from] hopr_protocol_pix::errors::PixError<SimplePseudonym>),
44
45 #[error(transparent)]
46 Other(#[from] GeneralError),
47}
48
49pub type Result<T> = std::result::Result<T, PacketError>;
50
51#[derive(Debug, Clone, Copy, Error, strum::AsRefStr)]
54#[strum(serialize_all = "snake_case")]
55pub enum ValidationErrorKind {
56 #[error("ticket signer does not match the sender")]
58 InvalidSigner,
59 #[error("ticket amount is lower than {0}")]
61 LowValue(HoprBalance),
62 #[error("ticket winning probability is lower than {0}")]
64 LowWinProb(WinningProbability),
65 #[error("channel {0} is closed or pending to close")]
67 ChannelClosed(ChannelId),
68 #[error("ticket epoch does not match channel epoch {0}")]
70 EpochMismatch(u32),
71 #[error("ticket index is lower than channel index {0}")]
73 IndexTooLow(u64),
74 #[error("ticket value is greater than remaining unrealized balance {1} in channel {0}")]
76 InsufficientFunds(ChannelId, HoprBalance),
77}
78
79#[derive(Debug, Clone, Error)]
81#[error("validation error of {ticket}: {kind}")]
82pub struct TicketValidationError {
83 pub kind: ValidationErrorKind,
85 pub ticket: Box<Ticket>,
87 pub issuer: Option<Address>,
91}
92
93#[cfg(test)]
94mod tests {
95 use hopr_types::{
96 crypto::prelude::{ChainKeypair, Keypair},
97 internal::prelude::TicketBuilder,
98 };
99
100 use super::*;
101
102 #[test]
103 fn test_validation_error_kind_display() {
104 let kind = ValidationErrorKind::LowWinProb(WinningProbability::ALWAYS);
105 assert_eq!(
106 kind.to_string(),
107 format!(
108 "ticket winning probability is lower than {}",
109 WinningProbability::ALWAYS
110 )
111 );
112 assert_eq!(kind.as_ref(), "low_win_prob");
113 }
114
115 #[test]
116 fn test_ticket_validation_error_display() {
117 let src = ChainKeypair::random();
118 let dst = ChainKeypair::random();
119
120 let ticket = TicketBuilder::zero_hop()
121 .counterparty(&dst)
122 .eth_challenge(Default::default())
123 .build_signed(&src, &Default::default())
124 .unwrap()
125 .leak();
126
127 let error = TicketValidationError {
128 kind: ValidationErrorKind::LowWinProb(WinningProbability::default()),
129 ticket: Box::new(ticket),
130 issuer: None,
131 };
132
133 assert_eq!(
134 error.to_string(),
135 format!(
136 "validation error of {ticket}: ticket winning probability is lower than {}",
137 WinningProbability::ALWAYS
138 )
139 );
140 }
141}