ckb_error/lib.rs
1//! Underlying error types used over ckb crates.
2
3use std::{error::Error as StdError, fmt, ops::Deref, sync::Arc};
4
5mod convert;
6mod internal;
7pub mod prelude;
8pub mod util;
9
10use derive_more::Display;
11pub use internal::{InternalError, InternalErrorKind, OtherError, SilentError};
12use prelude::*;
13
14/// A wrapper around a dynamic error type.
15#[derive(Clone)]
16pub struct AnyError(Arc<anyhow::Error>);
17
18/// A list specifying categories of ckb error.
19///
20/// This list is intended to grow over time and it is not recommended to exhaustively match against it.
21///
22/// It is used with [`Error`].
23///
24/// [`Error`]: ./struct.Error.html
25#[derive(Debug, Clone, Copy, Eq, PartialEq, Display)]
26pub enum ErrorKind {
27 /// It indicates that the underlying error is [`OutPointError`].
28 ///
29 /// [`OutPointError`]: ../ckb_types/core/error/enum.OutPointError.html
30 OutPoint,
31 /// It indicates that the underlying error is [`TransactionError`].
32 ///
33 /// [`TransactionError`]: ../ckb_verification/enum.TransactionError.html
34 Transaction,
35 /// It indicates that the underlying error is [`Reject`].
36 ///
37 /// [`Reject`]: ../ckb_tx_pool/error/enum.Reject.html
38 SubmitTransaction,
39 /// It indicates that the underlying error is [`TransactionScriptError`].
40 ///
41 /// [`TransactionScriptError`]: ../ckb_script/struct.TransactionScriptError.html
42 Script,
43 /// It indicates that the underlying error is [`HeaderError`].
44 ///
45 /// [`HeaderError`]: ../ckb_verification/struct.HeaderError.html
46 Header,
47 /// It indicates that the underlying error is [`BlockError`]
48 ///
49 /// [`BlockError`]: ../ckb_verification/struct.BlockError.html
50 Block,
51 /// It indicates that the underlying error is [`InternalError`]
52 ///
53 /// [`InternalError`]: ./struct.InternalError.html
54 Internal,
55 /// It indicates that the underlying error is [`DaoError`]
56 ///
57 /// [`DaoError`]: ../ckb_types/core/error/enum.OutPointError.html
58 Dao,
59 /// It indicates that the underlying error is [`SpecError`]
60 ///
61 /// [`SpecError`]: ../ckb_chain_spec/enum.SpecError.html
62 Spec,
63}
64
65def_error_base_on_kind!(Error, ErrorKind, "Top-level ckb error type.");
66
67impl<E> From<E> for AnyError
68where
69 E: StdError + Send + Sync + 'static,
70{
71 fn from(error: E) -> Self {
72 Self(Arc::new(error.into()))
73 }
74}
75
76impl Deref for AnyError {
77 type Target = Arc<anyhow::Error>;
78
79 fn deref(&self) -> &Self::Target {
80 &self.0
81 }
82}
83
84impl fmt::Display for AnyError {
85 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
86 self.0.fmt(f)
87 }
88}
89
90impl fmt::Debug for AnyError {
91 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
92 derive_more::Display::fmt(self, f)
93 }
94}
95/// Return whether the error's kind is `InternalErrorKind::Database`
96///
97/// ### Panic
98///
99/// Panic if the error kind is `InternalErrorKind::DataCorrupted`.
100/// If the database is corrupted, panic is better than handle it silently.
101pub fn is_internal_db_error(error: &Error) -> bool {
102 if error.kind() == ErrorKind::Internal {
103 let error_kind = error
104 .downcast_ref::<InternalError>()
105 .expect("error kind checked")
106 .kind();
107 if error_kind == InternalErrorKind::DataCorrupted {
108 panic!("{}", error)
109 } else {
110 return error_kind == InternalErrorKind::Database
111 || error_kind == InternalErrorKind::System;
112 }
113 }
114 false
115}