psbt_v2/
error.rs

1// SPDX-License-Identifier: CC0-1.0
2
3use core::fmt;
4
5use bitcoin::bip32::Xpub;
6
7/// Error combining two PSBTs, global extended public key has inconsistent key sources.
8#[derive(Debug, Clone, PartialEq, Eq)]
9#[non_exhaustive]
10pub struct InconsistentKeySourcesError(pub Xpub);
11
12impl fmt::Display for InconsistentKeySourcesError {
13    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
14        write!(f, "combining PSBT, key-source conflict for xpub {}", self.0)
15    }
16}
17
18#[cfg(feature = "std")]
19impl std::error::Error for InconsistentKeySourcesError {
20    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None }
21}
22
23/// An error while calculating the fee.
24#[derive(Debug, Clone, PartialEq, Eq)]
25#[non_exhaustive]
26pub enum FeeError {
27    /// Funding utxo error for input.
28    FundingUtxo(FundingUtxoError),
29    /// Integer overflow in fee calculation adding input.
30    InputOverflow,
31    /// Integer overflow in fee calculation adding output.
32    OutputOverflow,
33    /// Negative fee.
34    Negative,
35}
36
37impl fmt::Display for FeeError {
38    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39        use FeeError::*;
40
41        match *self {
42            FundingUtxo(ref e) => write_err!(f, "funding utxo error for input"; e),
43            InputOverflow => f.write_str("integer overflow in fee calculation adding input"),
44            OutputOverflow => f.write_str("integer overflow in fee calculation adding output"),
45            Negative => f.write_str("PSBT has a negative fee which is not allowed"),
46        }
47    }
48}
49
50#[cfg(feature = "std")]
51impl std::error::Error for FeeError {
52    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
53        use FeeError::*;
54
55        match *self {
56            FundingUtxo(ref e) => Some(e),
57            InputOverflow | OutputOverflow | Negative => None,
58        }
59    }
60}
61
62impl From<FundingUtxoError> for FeeError {
63    fn from(e: FundingUtxoError) -> Self { Self::FundingUtxo(e) }
64}
65
66/// An error getting the funding transaction for this input.
67#[derive(Debug, Clone, PartialEq, Eq)]
68#[non_exhaustive]
69pub enum FundingUtxoError {
70    /// The vout is out of bounds for non-witness transaction.
71    OutOfBounds {
72        /// The vout used as list index.
73        vout: usize,
74        /// The length of the utxo list.
75        len: usize,
76    },
77    /// No funding utxo found.
78    MissingUtxo,
79}
80
81impl fmt::Display for FundingUtxoError {
82    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83        use FundingUtxoError::*;
84
85        match *self {
86            OutOfBounds { vout, len } =>
87                write!(f, "vout {} out of bounds for tx list len: {}", vout, len),
88            MissingUtxo => write!(f, "no funding utxo found"),
89        }
90    }
91}
92
93#[cfg(feature = "std")]
94impl std::error::Error for FundingUtxoError {
95    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
96        use FundingUtxoError::*;
97
98        match *self {
99            OutOfBounds { .. } | MissingUtxo => None,
100        }
101    }
102}
103
104/// Formats error.
105///
106/// If `std` feature is OFF appends error source (delimited by `: `). We do this because
107/// `e.source()` is only available in std builds, without this macro the error source is lost for
108/// no-std builds.
109macro_rules! write_err {
110    ($writer:expr, $string:literal $(, $args:expr)*; $source:expr) => {
111        {
112            #[cfg(feature = "std")]
113            {
114                let _ = &$source;   // Prevents clippy warnings.
115                write!($writer, $string $(, $args)*)
116            }
117            #[cfg(not(feature = "std"))]
118            {
119                write!($writer, concat!($string, ": {}") $(, $args)*, $source)
120            }
121        }
122    }
123}
124pub(crate) use write_err;