sidestr_core/error.rs
1//! The one error type every fallible function in this crate returns.
2//!
3//! siding throws `Error` objects whose *messages* are the contract its tests
4//! match against (`/already claimed/`, `/below the minimum/`, `/not a hex
5//! script/`). The messages here keep that wording where a test in `tests/`
6//! depends on it, so a port of a siding test reads the same way.
7
8use crate::parents::Family;
9
10/// Everything that can go wrong, from a document that names a parent this
11/// validator does not carry to a block the rules refuse.
12#[derive(Debug, thiserror::Error)]
13pub enum Error {
14 /// The document names a parent alias that is not in the SPEC 3.2 table.
15 #[error("unknown parent \"{0}\": one of btc, tbtc4, xbt, txbt4, ltc, vtc (SPEC 3.2)")]
16 UnknownParent(String),
17 /// The alias is in the table but reserved: no validator carries its rules.
18 #[error(
19 "parent \"{alias}\" ({label}) is reserved: no validator carries its rules yet (SPEC 3.2)"
20 )]
21 ReservedParent {
22 /// The short alias, `ltc` or `vtc`.
23 alias: &'static str,
24 /// The human label from the table.
25 label: &'static str,
26 },
27 /// The document's parent hands down a header family other than the one
28 /// this state or chain is instantiated for (SPEC 3): a `State` over
29 /// `Stock` refuses a `txbt4` document, a `StateOf<Blake2bV2>` a `tbtc4` one.
30 #[error("the document's parent hands down the {0:?} header family, not the one this validator is instantiated for (SPEC 3.2: stock for btc/tbtc4, BLAKE2b for xbt/txbt4)")]
31 UnsupportedFamily(Family),
32 /// The chain document is malformed or names something this validator lacks.
33 #[error("chain document: {0}")]
34 Document(String),
35 /// JSON that does not parse or does not fit the document shape.
36 #[error("json: {0}")]
37 Json(#[from] serde_json::Error),
38 /// Bytes that do not decode as a block, transaction or hex.
39 #[error("encoding: {0}")]
40 Encoding(String),
41 /// A coinbase whose scriptSig does not start with a BIP 34 height push.
42 #[error("{0}")]
43 CoinbaseHeight(String),
44 /// A block the rules refused; `rules` lists the failed rule ids in order.
45 #[error("block {height} failed: {}", rules.join(", "))]
46 Rejected {
47 /// The height the block claimed.
48 height: u32,
49 /// The rule ids whose check returned `false`.
50 rules: Vec<String>,
51 },
52 /// A block that does not follow the tip, or whose hash is not the expected one.
53 #[error("{0}")]
54 Chain(String),
55 /// The block file's block 0 does not hash to the document's `genesisHash`.
56 #[error("genesis {found} is not the document's {expected}")]
57 GenesisMismatch {
58 /// The hash of block 0 as read.
59 found: String,
60 /// The document's `genesisHash`.
61 expected: String,
62 },
63 /// A transaction the producer's mempool policy or the rules refused.
64 #[error("{0}")]
65 Transaction(String),
66 /// Building or signing a block failed (no commitment output, a solution
67 /// too long for one push, a key that is not the challenge's).
68 #[error("{0}")]
69 Block(String),
70 /// A federation that cannot be built or used: signers out of range, a
71 /// duplicate signer, too few signatures, a key that is not a signer, or
72 /// `produce()` on a chain whose blocks come from a round.
73 #[error("federation: {0}")]
74 Federation(String),
75 /// The parent view: a node that cannot be reached or answers badly, a
76 /// cookie the node refuses, a script with no parent address, a
77 /// checkpoint over the data limit.
78 #[error("parent: {0}")]
79 Parent(String),
80 /// A secp256k1 failure: a bad key, a message that is not 32 bytes.
81 #[error("secp256k1: {0}")]
82 Secp(#[from] bitcoin::secp256k1::Error),
83 /// Filesystem trouble reading or writing the block file (feature `std`).
84 #[cfg(feature = "std")]
85 #[error("io: {0}")]
86 Io(#[from] std::io::Error),
87 /// The block file and its index disagree: an index entry that runs past
88 /// the end of `blocks.dat`, or a record whose `[u32 height][u32 size]`
89 /// prefix is not what the index entry says. Not gated on `std`: a
90 /// mirror's bytes are read the same way in a browser
91 /// ([`crate::mirror`]) as the file is on disk.
92 #[error("block file: {0}")]
93 BlockFile(String),
94}
95
96/// `Result` with this crate's [`Error`].
97pub type Result<T> = core::result::Result<T, Error>;