cometbft_light_client_verifier/
errors.rs1use core::time::Duration;
4
5use cometbft::{account::Id, Error as CometbftError};
6use flex_error::define_error;
7use serde::{Deserialize, Serialize};
8
9use crate::{
10 operations::voting_power::VotingPowerTally,
11 prelude::*,
12 types::{Hash, Height, Time, Validator, ValidatorAddress, ValidatorSet},
13};
14
15define_error! {
16 #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
17 VerificationError {
18 Cometbft
19 [ CometbftError ]
20 | _ | { "CometBFT error" },
21
22 HeaderFromTheFuture
23 {
24 header_time: Time,
25 now: Time,
26 max_clock_drift: Duration,
27 }
28 | e | {
29 format_args!("header from the future: header_time={0} now={1} max_clock_drift={2:?}",
30 e.header_time, e.now, e.max_clock_drift)
31 },
32
33 NotEnoughTrust
34 {
35 tally: VotingPowerTally,
36 }
37 | e | {
38 format_args!("not enough trust because insufficient validators overlap: {0}",
39 e.tally)
40 },
41
42 InsufficientSignersOverlap
43 {
44 tally: VotingPowerTally,
45 }
46 | e | {
47 format_args!("insufficient signers overlap: {0}",
48 e.tally)
49 },
50
51 DuplicateValidator
52 {
53 address: ValidatorAddress,
54 }
55 | e | {
56 format_args!("duplicate validator with address {0}",
57 e.address)
58 },
59
60 MissingSignature
61 | _ | {
62 format_args!("missing signature")
63 },
64
65 InvalidSignature
66 {
67 signature: Vec<u8>,
68 validator: Box<Validator>,
69 sign_bytes: Vec<u8>,
70 }
71 | e | {
72 format_args!("failed to verify signature `{:?}` with validator `{:?}` on sign_bytes `{:?}`",
73 e.signature, e.validator, e.sign_bytes)
74 },
75
76 InvalidCommitValue
77 {
78 header_hash: Hash,
79 commit_hash: Hash,
80 }
81 | e | {
82 format_args!("invalid commit value: header_hash={0} commit_hash={1}",
83 e.header_hash, e.commit_hash)
84 },
85
86 InvalidNextValidatorSet
87 {
88 header_next_validators_hash: Hash,
89 next_validators_hash: Hash,
90 }
91 | e | {
92 format_args!("invalid next validator set: header_next_validators_hash={0} next_validators_hash={1}",
93 e.header_next_validators_hash, e.next_validators_hash)
94 },
95
96 InvalidValidatorSet
97 {
98 header_validators_hash: Hash,
99 validators_hash: Hash,
100 }
101 | e | {
102 format_args!("invalid validator set: header_validators_hash={0} validators_hash={1}",
103 e.header_validators_hash, e.validators_hash)
104 },
105
106 NonIncreasingHeight
107 {
108 got: Height,
109 expected: Height,
110 }
111 | e | {
112 format_args!("non increasing height: got={0} expected={1}",
113 e.got, e.expected)
114 },
115
116 ChainIdMismatch
117 {
118 got: String,
119 expected: String,
120 }
121 | e | {
122 format_args!("chain-id mismatch: got={0} expected={1}",
123 e.got, e.expected)
124 },
125
126 NonMonotonicBftTime
127 {
128 header_bft_time: Time,
129 trusted_header_bft_time: Time,
130 }
131 | e | {
132 format_args!("non monotonic BFT time: header_bft_time={0} trusted_header_bft_time={1}",
133 e.header_bft_time, e.trusted_header_bft_time)
134 },
135
136 NotWithinTrustPeriod
137 {
138 expires_at: Time,
139 now: Time,
140 }
141 | e | {
142 format_args!("not within trusting period: expires_at={0} now={1}",
143 e.expires_at, e.now)
144 },
145
146 NoSignatureForCommit
147 | _ | { "no signatures for commit" },
148
149 MismatchPreCommitLength
150 {
151 pre_commit_length: usize,
152 validator_length: usize,
153 }
154 | e | {
155 format_args!(
156 "pre-commit length: {} doesn't match validator length: {}",
157 e.pre_commit_length,
158 e.validator_length
159 )
160 },
161
162 FaultySigner
163 {
164 signer: Id,
165 validator_set: ValidatorSet
166 }
167 | e | {
168 format_args!(
169 "Found a faulty signer ({}) not present in the validator set",
170 e.signer,
171 )
172 },
173
174 }
175}
176
177pub trait ErrorExt {
179 fn not_enough_trust(&self) -> Option<VotingPowerTally>;
182
183 fn has_expired(&self) -> bool;
186
187 fn is_timeout(&self) -> Option<Duration>;
190
191 fn is_io(&self) -> bool;
193
194 fn is_height_too_high(&self) -> bool;
197}
198
199impl ErrorExt for VerificationErrorDetail {
200 fn not_enough_trust(&self) -> Option<VotingPowerTally> {
201 match &self {
202 Self::NotEnoughTrust(e) => Some(e.tally),
203 _ => None,
204 }
205 }
206
207 fn has_expired(&self) -> bool {
208 matches!(self, Self::NotWithinTrustPeriod { .. })
209 }
210
211 fn is_timeout(&self) -> Option<Duration> {
212 None
213 }
214
215 fn is_io(&self) -> bool {
216 false
217 }
218
219 fn is_height_too_high(&self) -> bool {
220 false
221 }
222}