cometbft_light_client/
errors.rs1use std::{fmt::Debug, time::Duration};
4
5use crossbeam_channel as crossbeam;
6use flex_error::{define_error, DisplayError, TraceError};
7
8pub use crate::verifier::errors::ErrorExt;
10use crate::{
11 components::io::IoError,
12 verifier::{
13 errors::VerificationErrorDetail,
14 operations::voting_power::VotingPowerTally,
15 options::Options,
16 types::{Hash, Height, LightBlock, PeerId, Status},
17 },
18};
19
20#[cfg(feature = "sled")]
21type SledError = TraceError<sled::Error>;
22
23#[cfg(not(feature = "sled"))]
24type SledError = flex_error::NoSource;
25
26define_error! {
27 #[derive(Debug)]
28 Error {
29 Io
30 [ IoError ]
31 | _ | { "io error" },
32
33 NoPrimary
34 | _ | { "no primary" },
35
36 NoWitnesses
37 | _ | { "no witnesses" },
38
39 NoWitnessesLeft
40 | _ | { "no witnesses left" },
41
42 ForkDetected
43 { peers: Vec<PeerId> }
44 | e | {
45 format_args!("fork detected peers={0:?}",
46 e.peers)
47 },
48
49 NoInitialTrustedState
50 | _ | { "no initial trusted state" },
51
52 NoTrustedState
53 { status: Status }
54 | e | {
55 format_args!("no trusted state with status {:?}",
56 e.status)
57 },
58
59 TargetLowerThanTrustedState
60 {
61 target_height: Height,
62 trusted_height: Height,
63 }
64 | e | {
65 format_args!("target height ({0}) is lower than trusted state ({1})",
66 e.target_height, e.trusted_height)
67 },
68
69 HeightTooHigh
70 {
71 height: Height,
72 latest_height: Height,
73 }
74 |e| {
75 format_args!("height ({0}) is higher than latest height ({1})",
76 e.height, e.latest_height)
77 },
78
79 TrustedStateOutsideTrustingPeriod
80 {
81 trusted_state: Box<LightBlock>,
82 options: Options,
83 }
84 | _ | {
85 format_args!("trusted state outside of trusting period")
86 },
87
88 BisectionFailed
89 {
90 target_height: Height,
91 trusted_height: Height
92 }
93 | e | {
94 format_args!("bisection for target at height {0} failed when reached trusted state at height {1}",
95 e.target_height, e.trusted_height)
96 },
97
98 InvalidLightBlock
99 [ DisplayError<VerificationErrorDetail> ]
100 | _ | { "invalid light block" },
101
102 InvalidAdjacentHeaders
103 {
104 hash1: Hash,
105 hash2: Hash,
106 }
107 | e | {
108 format_args!("hash mismatch between two adjacent headers: {0} != {1}",
109 e.hash1, e.hash2)
110 },
111
112 MissingLastBlockId
113 { height: Height }
114 | e | {
115 format_args!("missing last_block_id for header at height {0}",
116 e.height)
117 },
118
119 ChannelDisconnected
120 | _ | { "internal channel disconnected" },
121
122 Sled
123 [ SledError ]
124 | _ | { "sled error" },
125
126 SerdeCbor
127 [ TraceError<serde_cbor::Error> ]
128 | _ | { "serde cbor error" },
129
130 }
131}
132
133impl ErrorExt for ErrorDetail {
134 fn not_enough_trust(&self) -> Option<VotingPowerTally> {
135 if let Self::InvalidLightBlock(e) = self {
136 e.source.not_enough_trust()
137 } else {
138 None
139 }
140 }
141
142 fn has_expired(&self) -> bool {
143 if let Self::InvalidLightBlock(e) = self {
144 e.source.has_expired()
145 } else {
146 false
147 }
148 }
149
150 fn is_timeout(&self) -> Option<Duration> {
152 if let Self::Io(e) = self {
153 e.source.is_timeout()
154 } else {
155 None
156 }
157 }
158
159 fn is_io(&self) -> bool {
160 matches!(self, Self::Io(_))
161 }
162
163 fn is_height_too_high(&self) -> bool {
164 matches!(self, Self::HeightTooHigh { .. })
165 }
166}
167
168impl Error {
169 pub fn send<T>(_e: crossbeam::SendError<T>) -> Error {
170 Error::channel_disconnected()
171 }
172
173 pub fn recv(_e: crossbeam::RecvError) -> Error {
174 Error::channel_disconnected()
175 }
176}