zebra_chain/
error.rs

1//! Errors that can occur inside any `zebra-chain` submodule.
2
3use std::{io, sync::Arc};
4use thiserror::Error;
5use zcash_protocol::value::BalanceError;
6
7// TODO: Move all these enums into a common enum at the bottom.
8
9/// Errors related to random bytes generation.
10#[derive(Error, Copy, Clone, Debug, PartialEq, Eq)]
11pub enum RandError {
12    /// Error of the `try_fill_bytes` function.
13    #[error("failed to generate a secure stream of random bytes")]
14    FillBytes,
15}
16
17/// An error type pertaining to shielded notes.
18#[derive(Error, Copy, Clone, Debug, PartialEq, Eq)]
19pub enum NoteError {
20    /// Errors of type `RandError`.
21    #[error("Randomness generation failure")]
22    InsufficientRandomness(#[from] RandError),
23    /// Error of `pallas::Point::from_bytes()` for new rho randomness.
24    #[error("failed to generate an Orchard note's rho.")]
25    InvalidRho,
26}
27
28/// An error type pertaining to note commitments.
29#[derive(Error, Copy, Clone, Debug, PartialEq, Eq)]
30pub enum NoteCommitmentError {
31    /// Errors of type `RandError`.
32    #[error("Randomness generation failure")]
33    InsufficientRandomness(#[from] RandError),
34    /// Error of `jubjub::AffinePoint::try_from`.
35    #[error("failed to generate a sapling::NoteCommitment from a diversifier")]
36    InvalidDiversifier,
37}
38
39/// An error type pertaining to key generation, parsing, modification,
40/// randomization.
41#[derive(Error, Copy, Clone, Debug, PartialEq, Eq)]
42pub enum KeyError {
43    /// Errors of type `RandError`.
44    #[error("Randomness generation failure")]
45    InsufficientRandomness(#[from] RandError),
46}
47
48/// An error type pertaining to payment address generation, parsing,
49/// modification, diversification.
50#[derive(Error, Copy, Clone, Debug, PartialEq, Eq)]
51pub enum AddressError {
52    /// Errors of type `RandError`.
53    #[error("Randomness generation failure")]
54    InsufficientRandomness(#[from] RandError),
55    /// Errors pertaining to diversifier generation.
56    #[error("Randomness did not hash into the Jubjub group for producing a new diversifier")]
57    DiversifierGenerationFailure,
58}
59
60/// `zebra-chain`'s errors
61#[derive(Clone, Error, Debug)]
62pub enum Error {
63    /// Invalid consensus branch ID.
64    #[error("invalid consensus branch id")]
65    InvalidConsensusBranchId,
66
67    /// The error type for I/O operations of the `Read`, `Write`, `Seek`, and associated traits.
68    #[error(transparent)]
69    Io(#[from] Arc<io::Error>),
70
71    /// The transaction is missing a network upgrade.
72    #[error("the transaction is missing a network upgrade")]
73    MissingNetworkUpgrade,
74
75    /// Invalid amount.
76    #[error(transparent)]
77    Amount(#[from] BalanceError),
78
79    /// Zebra's type could not be converted to its librustzcash equivalent.
80    #[error("Zebra's type could not be converted to its librustzcash equivalent: {0}")]
81    Conversion(String),
82}
83
84/// Allow converting `io::Error` to `Error`; we need this since we
85/// use `Arc<io::Error>` in `Error::Conversion`.
86impl From<io::Error> for Error {
87    fn from(value: io::Error) -> Self {
88        Arc::new(value).into()
89    }
90}
91
92// We need to implement this manually because io::Error does not implement
93// PartialEq.
94impl PartialEq for Error {
95    fn eq(&self, other: &Self) -> bool {
96        match self {
97            Error::InvalidConsensusBranchId => matches!(other, Error::InvalidConsensusBranchId),
98            Error::Io(e) => {
99                if let Error::Io(o) = other {
100                    // Not perfect, but good enough for testing, which
101                    // is the main purpose for our usage of PartialEq for errors
102                    e.to_string() == o.to_string()
103                } else {
104                    false
105                }
106            }
107            Error::MissingNetworkUpgrade => matches!(other, Error::MissingNetworkUpgrade),
108            Error::Amount(e) => matches!(other, Error::Amount(o) if e == o),
109            Error::Conversion(e) => matches!(other, Error::Conversion(o) if e == o),
110        }
111    }
112}
113
114impl Eq for Error {}