ckb_verification/error.rs
1use ckb_error::{Error, def_error_base_on_kind, prelude::*};
2use ckb_types::{core::Version, packed::Byte32};
3use derive_more::Display;
4
5pub use ckb_types::core::{
6 EpochNumberWithFraction,
7 error::{TransactionError, TransactionErrorSource},
8};
9
10/// A list specifying categories of ckb header error.
11///
12/// This list is intended to grow over time and it is not recommended to exhaustively match against it.
13///
14/// It is used with the [`HeaderError`].
15///
16/// [`HeaderError`]: ../ckb_verification/struct.HeaderError.html
17#[derive(Debug, PartialEq, Eq, Clone, Copy, Display)]
18pub enum HeaderErrorKind {
19 /// It indicates that the underlying error is [`InvalidParentError`].
20 ///
21 /// [`InvalidParentError`]: ../ckb_verification/struct.InvalidParentError.html
22 InvalidParent,
23 /// It indicates that the underlying error is [`PowError`].
24 ///
25 /// [`PowError`]: ../ckb_verification/enum.PowError.html
26 Pow,
27 /// It indicates that the underlying error is [`TimestampError`].
28 ///
29 /// [`TimestampError`]: ../ckb_verification/enum.TimestampError.html
30 Timestamp,
31 /// It indicates that the underlying error is [`NumberError`].
32 ///
33 /// [`NumberError`]: ../ckb_verification/struct.NumberError.html
34 Number,
35 /// It indicates that the underlying error is [`EpochError`].
36 ///
37 /// [`EpochError`]: ../ckb_verification/enum.EpochError.html
38 Epoch,
39 /// It indicates that the underlying error is [`BlockVersionError`].
40 ///
41 /// [`BlockVersionError`]: ../ckb_verification/struct.BlockVersionError.html
42 Version,
43}
44
45def_error_base_on_kind!(
46 HeaderError,
47 HeaderErrorKind,
48 "Errors due the fact that the header rule is not respected."
49);
50
51/// A list specifying categories of ckb block error.
52///
53/// This list is intended to grow over time and it is not recommended to exhaustively match against it.
54///
55/// It is used with the [`BlockError`].
56///
57/// [`BlockError`]: ../ckb_verification/struct.BlockError.html
58#[derive(Debug, PartialEq, Eq, Clone, Copy, Display)]
59pub enum BlockErrorKind {
60 /// There are duplicated proposal transactions.
61 ProposalTransactionDuplicate,
62
63 /// There are duplicate committed transactions.
64 CommitTransactionDuplicate,
65
66 /// The calculated Merkle tree hash of proposed transactions does not match the one in the header.
67 ProposalTransactionsHash,
68
69 /// The calculated Merkle tree hash of committed transactions does not match the one in the header.
70 TransactionsRoot,
71
72 /// The calculated dao field does not match with the one in the header.
73 InvalidDAO,
74
75 /// It indicates that the underlying error is [`BlockTransactionsError`].
76 ///
77 /// [`BlockTransactionsError`]: ../ckb_verification/struct.BlockTransactionsError.html
78 BlockTransactions,
79
80 /// It indicates that the underlying error is [`UnknownParentError`].
81 ///
82 /// [`UnknownParentError`]: ../ckb_verification/struct.UnknownParentError.html
83 UnknownParent,
84
85 /// It indicates that the underlying error is [`UnclesError`].
86 ///
87 /// [`UnclesError`]: ../ckb_verification/enum.UnclesError.html
88 Uncles,
89
90 /// It indicates that the underlying error is [`CellbaseError`].
91 ///
92 /// [`CellbaseError`]: ../ckb_verification/enum.CellbaseError.html
93 Cellbase,
94
95 /// It indicates that the underlying error is [`CommitError`].
96 ///
97 /// [`CommitError`]: ../ckb_verification/struct.CommitError.html
98 Commit,
99
100 /// The number of block proposals exceeds limit.
101 ExceededMaximumProposalsLimit,
102
103 /// Total cycles of the block transactions exceed limit.
104 ExceededMaximumCycles,
105
106 /// Total bytes of block exceeds limit.
107 ExceededMaximumBlockBytes,
108
109 /// Empty block extension.
110 EmptyBlockExtension,
111
112 /// Total bytes of block extension exceeds limit.
113 ExceededMaximumBlockExtensionBytes,
114
115 /// No block extension.
116 ///
117 /// The block extension should be existed after light client supported.
118 NoBlockExtension,
119
120 /// The data length of block extension mismatches.
121 InvalidBlockExtension,
122
123 /// The block has unknown field.
124 UnknownFields,
125
126 /// The calculated extra-hash does not match with the one in the header.
127 InvalidExtraHash,
128
129 /// The calculated hash of chain root does not match with the one in the header.
130 InvalidChainRoot,
131}
132
133def_error_base_on_kind!(
134 BlockError,
135 BlockErrorKind,
136 "Errors due the fact that the block rule is not respected."
137);
138
139/// Errors occur during block transactions verification.
140#[derive(Error, Debug)]
141#[error("BlockTransactionsError(index: {index}, error: {error})")]
142pub struct BlockTransactionsError {
143 /// The index of the first erroneous transaction.
144 pub index: u32,
145 /// The underlying error to that erroneous transaction.
146 pub error: Error,
147}
148
149/// Cannot access the parent block to the canonical chain.
150#[derive(Error, Debug, PartialEq, Eq, Clone)]
151#[error("UnknownParentError(parent_hash: {parent_hash})")]
152pub struct UnknownParentError {
153 /// The hash of parent block.
154 pub parent_hash: Byte32,
155}
156
157/// Errors due to the fact that the 2pc rule is not respected.
158///
159/// See also [Two-Step Transaction Confirmation](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0020-ckb-consensus-protocol/0020-ckb-consensus-protocol.md#two-step-transaction-confirmation)
160#[derive(Error, Debug, PartialEq, Eq, Clone, Display)]
161pub enum CommitError {
162 /// There are blocks required at 2pc verification but not found.
163 AncestorNotFound,
164 /// There are block transactions that have not been proposed in the proposal window.
165 Invalid,
166}
167
168/// Errors due to the fact that the cellbase rule is not respected.
169///
170/// See more about cellbase transaction: [cellbase transaction]
171///
172/// [cellbase transaction]: https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0022-transaction-structure/0022-transaction-structure.md#exceptions
173#[derive(Error, Debug, PartialEq, Eq, Clone, Display)]
174pub enum CellbaseError {
175 /// The cellbase input is unexpected. The structure reference of correct cellbase input: [`new_cellbase_input`].
176 ///
177 /// [`new_cellbase_input`]: https://github.com/nervosnetwork/ckb/blob/ee0ccecd87013821a2e68120ba3510393c0373e7/util/types/src/extension/shortcuts.rs#L107-L109
178 InvalidInput,
179 /// The cellbase output capacity is not equal to the total block reward.
180 InvalidRewardAmount,
181 /// The cellbase output lock does not match with the target lock.
182 ///
183 /// As for 0 ~ PROPOSAL_WINDOW.farthest blocks, cellbase outputs should be empty; otherwise, lock of first cellbase output should match with the target block.
184 ///
185 /// Assumes the current block number is `i`, then its target block is that: (1) on that same chain with current block; (2) number is `i - PROPOSAL_WINDOW.farthest - 1`.
186 InvalidRewardTarget,
187 /// The cellbase witness is not in [`CellbaseWitness`] format.
188 ///
189 /// [`CellbaseWitness`]: ../ckb_types/packed/struct.CellbaseWitness.html
190 InvalidWitness,
191 /// The cellbase type script is not none.
192 InvalidTypeScript,
193 /// The length of cellbase outputs and outputs-data should be equal and less than `1`.
194 InvalidOutputQuantity,
195 /// There are multiple cellbase transactions inside the same block.
196 InvalidQuantity,
197 /// The first block transaction is not a valid cellbase transaction.
198 ///
199 /// See also [`is_cellbase`].
200 ///
201 /// [`is_cellbase`]: https://github.com/nervosnetwork/ckb/blob/ee0ccecd87013821a2e68120ba3510393c0373e7/util/types/src/core/views.rs#L387-L389
202 InvalidPosition,
203 /// The cellbase output-data is not empty.
204 InvalidOutputData,
205 /// The cellbase output lock is Invalid.
206 InvalidOutputLock,
207}
208
209/// Errors due to the fact that the uncle rule is not respected.
210#[derive(Error, Debug, PartialEq, Eq, Clone)]
211pub enum UnclesError {
212 /// The number of block uncles exceeds limit.
213 #[error("OverCount(max: {max}, actual: {actual})")]
214 OverCount {
215 /// The limited number of block uncles.
216 max: u32,
217 /// The actual number of block uncles.
218 actual: u32,
219 },
220
221 /// There is an uncle whose number is greater than or equal to current block number.
222 #[error("InvalidNumber")]
223 InvalidNumber,
224
225 /// There is an uncle who belongs to a different epoch from the current block.
226 #[error("InvalidTarget")]
227 InvalidTarget,
228
229 /// There is an uncle who belongs to a different epoch from the current block.
230 #[error("InvalidDifficultyEpoch")]
231 InvalidDifficultyEpoch,
232
233 /// There is an uncle whose proposals-hash does not match with the calculated result.
234 #[error("ProposalsHash")]
235 ProposalsHash,
236
237 /// There is an uncle whose proposals have duplicated items.
238 #[error("ProposalDuplicate")]
239 ProposalDuplicate,
240
241 /// There are duplicated uncles in the current block.
242 #[error("Duplicate({0})")]
243 Duplicate(Byte32),
244
245 /// There is an uncle that has already been included before.
246 #[error("DoubleInclusion({0})")]
247 DoubleInclusion(Byte32),
248
249 /// The depth of uncle descendant exceeds limit.
250 #[error("DescendantLimit")]
251 DescendantLimit,
252
253 /// The number of uncle proposals exceeds limit.
254 #[error("ExceededMaximumProposalsLimit")]
255 ExceededMaximumProposalsLimit,
256}
257
258/// The block version is unexpected.
259#[derive(Error, Debug, PartialEq, Eq, Clone)]
260#[error("BlockVersionError(expected: {expected}, actual: {actual})")]
261pub struct BlockVersionError {
262 /// The expected block version.
263 pub expected: Version,
264 /// The actual block version.
265 pub actual: Version,
266}
267
268/// The block's parent is marked as invalid.
269#[derive(Error, Debug, PartialEq, Eq, Clone)]
270#[error("InvalidParentError(parent_hash: {parent_hash})")]
271pub struct InvalidParentError {
272 /// The parent block hash.
273 pub parent_hash: Byte32,
274}
275
276/// Errors due to the fact that the pow rule is not respected.
277#[derive(Error, Debug, PartialEq, Eq, Clone)]
278pub enum PowError {
279 /// Error occurs during PoW verification.
280 #[error(
281 "InvalidNonce: please set logger.filter to \"info,ckb-pow=debug\" for detailed PoW verification information"
282 )]
283 InvalidNonce,
284}
285
286/// Errors due to the fact that the block timestamp rule is not respected.
287#[derive(Error, Debug, PartialEq, Eq, Clone)]
288pub enum TimestampError {
289 /// The block timestamp is older than the allowed oldest timestamp.
290 #[error("BlockTimeTooOld(min: {min}, actual: {actual})")]
291 BlockTimeTooOld {
292 /// The allowed oldest block timestamp.
293 min: u64,
294 /// The actual block timestamp.
295 actual: u64,
296 },
297
298 /// The block timestamp is newer than the allowed newest timestamp.
299 #[error("BlockTimeTooNew(max: {max}, actual: {actual})")]
300 BlockTimeTooNew {
301 /// The allowed newest block timestamp.
302 max: u64,
303 /// The actual block timestamp.
304 actual: u64,
305 },
306}
307
308impl TimestampError {
309 /// Return `true` if this error is `TimestampError::BlockTimeTooNew`.
310 #[doc(hidden)]
311 pub fn is_too_new(&self) -> bool {
312 match self {
313 Self::BlockTimeTooOld { .. } => false,
314 Self::BlockTimeTooNew { .. } => true,
315 }
316 }
317}
318
319/// The block number is not equal to parent number + `1`.
320/// Specially genesis block number is `0`.
321#[derive(Error, Debug, PartialEq, Eq, Clone)]
322#[error("NumberError(expected: {expected}, actual: {actual})")]
323pub struct NumberError {
324 /// The expected block number.
325 pub expected: u64,
326 /// The actual block number.
327 pub actual: u64,
328}
329
330/// Errors due to the fact that the block epoch is not expected.
331#[derive(Error, Debug, PartialEq, Eq, Clone)]
332pub enum EpochError {
333 /// The format of header epoch is malformed.
334 #[error("Malformed(value: {value:#})")]
335 Malformed {
336 /// The malformed header epoch.
337 value: EpochNumberWithFraction,
338 },
339
340 /// The header epoch is not continuous.
341 #[error("NonContinuous(current: {current:#}, parent: {parent:#})")]
342 NonContinuous {
343 /// The current header epoch.
344 current: EpochNumberWithFraction,
345 /// The parent header epoch.
346 parent: EpochNumberWithFraction,
347 },
348
349 /// The compact-target of block epoch is unexpected.
350 #[error("TargetMismatch(expected: {expected:x}, actual: {actual:x})")]
351 TargetMismatch {
352 /// The expected compact-target of block epoch.
353 expected: u32,
354 /// The actual compact-target of block epoch.
355 actual: u32,
356 },
357
358 /// The number of block epoch is unexpected.
359 #[error("NumberMismatch(expected: {expected}, actual: {actual})")]
360 NumberMismatch {
361 /// The expected number of block epoch.
362 expected: u64,
363 /// The actual number of block epoch.
364 actual: u64,
365 },
366}
367
368impl HeaderError {
369 /// Downcast `HeaderError` to `TimestampError` then check [`TimestampError::is_too_new`].
370 ///
371 /// Note: if the header is invalid, that may also be grounds for disconnecting the peer,
372 /// However, there is a circumstance where that does not hold:
373 /// if the header's timestamp is more than ALLOWED_FUTURE_BLOCKTIME ahead of our current time.
374 /// In that case, the header may become valid in the future,
375 /// and we don't want to disconnect a peer merely for serving us one too-far-ahead block header,
376 /// to prevent an attacker from splitting the network by mining a block right at the ALLOWED_FUTURE_BLOCKTIME boundary.
377 ///
378 /// [`TimestampError::is_too_new`]
379 #[doc(hidden)]
380 pub fn is_too_new(&self) -> bool {
381 self.downcast_ref::<TimestampError>()
382 .map(|e| e.is_too_new())
383 .unwrap_or(false)
384 }
385}