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}