hopr_crypto_packet/
errors.rs1use std::fmt::Debug;
2
3use hopr_types::{
4 crypto::errors::CryptoError,
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] hopr_crypto_sphinx::errors::SphinxError),
41
42 #[error(transparent)]
43 Other(#[from] GeneralError),
44}
45
46pub type Result<T> = std::result::Result<T, PacketError>;
47
48#[derive(Debug, Clone, Copy, Error, strum::AsRefStr)]
51#[strum(serialize_all = "snake_case")]
52pub enum ValidationErrorKind {
53 #[error("ticket signer does not match the sender")]
55 InvalidSigner,
56 #[error("ticket amount is lower than {0}")]
58 LowValue(HoprBalance),
59 #[error("ticket winning probability is lower than {0}")]
61 LowWinProb(WinningProbability),
62 #[error("channel {0} is closed or pending to close")]
64 ChannelClosed(ChannelId),
65 #[error("ticket epoch does not match channel epoch {0}")]
67 EpochMismatch(u32),
68 #[error("ticket index is lower than channel index {0}")]
70 IndexTooLow(u64),
71 #[error("ticket value is greater than remaining unrealized balance {1} in channel {0}")]
73 InsufficientFunds(ChannelId, HoprBalance),
74}
75
76#[derive(Debug, Clone, Error)]
78#[error("validation error of {ticket}: {kind}")]
79pub struct TicketValidationError {
80 pub kind: ValidationErrorKind,
82 pub ticket: Box<Ticket>,
84 pub issuer: Option<Address>,
88}
89
90#[cfg(test)]
91mod tests {
92 use hopr_types::{
93 crypto::prelude::{ChainKeypair, Keypair},
94 internal::prelude::TicketBuilder,
95 };
96
97 use super::*;
98
99 #[test]
100 fn test_validation_error_kind_display() {
101 let kind = ValidationErrorKind::LowWinProb(WinningProbability::ALWAYS);
102 assert_eq!(
103 kind.to_string(),
104 format!(
105 "ticket winning probability is lower than {}",
106 WinningProbability::ALWAYS
107 )
108 );
109 assert_eq!(kind.as_ref(), "low_win_prob");
110 }
111
112 #[test]
113 fn test_ticket_validation_error_display() {
114 let src = ChainKeypair::random();
115 let dst = ChainKeypair::random();
116
117 let ticket = TicketBuilder::zero_hop()
118 .counterparty(&dst)
119 .eth_challenge(Default::default())
120 .build_signed(&src, &Default::default())
121 .unwrap()
122 .leak();
123
124 let error = TicketValidationError {
125 kind: ValidationErrorKind::LowWinProb(WinningProbability::default()),
126 ticket: Box::new(ticket),
127 issuer: None,
128 };
129
130 assert_eq!(
131 error.to_string(),
132 format!(
133 "validation error of {ticket}: ticket winning probability is lower than {}",
134 WinningProbability::ALWAYS
135 )
136 );
137 }
138}