jitash_bdk/
error.rs

1// Bitcoin Dev Kit
2// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
3//
4// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
5//
6// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
7// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
8// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
9// You may not use this file except in accordance with one or both of these
10// licenses.
11
12use std::fmt;
13
14use crate::bitcoin::Network;
15use crate::{descriptor, wallet};
16use bitcoin::{OutPoint, Txid};
17
18/// Errors that can be thrown by the [`Wallet`](crate::wallet::Wallet)
19#[derive(Debug)]
20pub enum Error {
21    /// Wrong number of bytes found when trying to convert to u32
22    InvalidU32Bytes(Vec<u8>),
23    /// Generic error
24    Generic(String),
25    /// This error is thrown when trying to convert Bare and Public key script to address
26    ScriptDoesntHaveAddressForm,
27    /// Cannot build a tx without recipients
28    NoRecipients,
29    /// `manually_selected_only` option is selected but no utxo has been passed
30    NoUtxosSelected,
31    /// Output created is under the dust limit, 546 satoshis
32    OutputBelowDustLimit(usize),
33    /// Wallet's UTXO set is not enough to cover recipient's requested plus fee
34    InsufficientFunds {
35        /// Sats needed for some transaction
36        needed: u64,
37        /// Sats available for spending
38        available: u64,
39    },
40    /// Branch and bound coin selection possible attempts with sufficiently big UTXO set could grow
41    /// exponentially, thus a limit is set, and when hit, this error is thrown
42    BnBTotalTriesExceeded,
43    /// Branch and bound coin selection tries to avoid needing a change by finding the right inputs for
44    /// the desired outputs plus fee, if there is not such combination this error is thrown
45    BnBNoExactMatch,
46    /// Happens when trying to spend an UTXO that is not in the internal database
47    UnknownUtxo,
48    /// Thrown when a tx is not found in the internal database
49    TransactionNotFound,
50    /// Happens when trying to bump a transaction that is already confirmed
51    TransactionConfirmed,
52    /// Trying to replace a tx that has a sequence >= `0xFFFFFFFE`
53    IrreplaceableTransaction,
54    /// When bumping a tx the fee rate requested is lower than required
55    FeeRateTooLow {
56        /// Required fee rate (satoshi/vbyte)
57        required: crate::types::FeeRate,
58    },
59    /// When bumping a tx the absolute fee requested is lower than replaced tx absolute fee
60    FeeTooLow {
61        /// Required fee absolute value (satoshi)
62        required: u64,
63    },
64    /// Node doesn't have data to estimate a fee rate
65    FeeRateUnavailable,
66    /// In order to use the [`TxBuilder::add_global_xpubs`] option every extended
67    /// key in the descriptor must either be a master key itself (having depth = 0) or have an
68    /// explicit origin provided
69    ///
70    /// [`TxBuilder::add_global_xpubs`]: crate::wallet::tx_builder::TxBuilder::add_global_xpubs
71    MissingKeyOrigin(String),
72    /// Error while working with [`keys`](crate::keys)
73    Key(crate::keys::KeyError),
74    /// Descriptor checksum mismatch
75    ChecksumMismatch,
76    /// Spending policy is not compatible with this [`KeychainKind`](crate::types::KeychainKind)
77    SpendingPolicyRequired(crate::types::KeychainKind),
78    /// Error while extracting and manipulating policies
79    InvalidPolicyPathError(crate::descriptor::policy::PolicyError),
80    /// Signing error
81    Signer(crate::wallet::signer::SignerError),
82    /// Invalid network
83    InvalidNetwork {
84        /// requested network, for example what is given as bdk-cli option
85        requested: Network,
86        /// found network, for example the network of the bitcoin node
87        found: Network,
88    },
89    #[cfg(feature = "verify")]
90    /// Transaction verification error
91    Verification(crate::wallet::verify::VerifyError),
92
93    /// Progress value must be between `0.0` (included) and `100.0` (included)
94    InvalidProgressValue(f32),
95    /// Progress update error (maybe the channel has been closed)
96    ProgressUpdateError,
97    /// Requested outpoint doesn't exist in the tx (vout greater than available outputs)
98    InvalidOutpoint(OutPoint),
99
100    /// Error related to the parsing and usage of descriptors
101    Descriptor(crate::descriptor::error::Error),
102    /// Encoding error
103    Encode(bitcoin::consensus::encode::Error),
104    /// Miniscript error
105    Miniscript(miniscript::Error),
106    /// Miniscript PSBT error
107    MiniscriptPsbt(MiniscriptPsbtError),
108    /// BIP32 error
109    Bip32(bitcoin::util::bip32::Error),
110    /// A secp256k1 error
111    Secp256k1(bitcoin::secp256k1::Error),
112    /// Error serializing or deserializing JSON data
113    Json(serde_json::Error),
114    /// Hex decoding error
115    Hex(bitcoin::hashes::hex::Error),
116    /// Partially signed bitcoin transaction error
117    Psbt(bitcoin::util::psbt::Error),
118    /// Partially signed bitcoin transaction parse error
119    PsbtParse(bitcoin::util::psbt::PsbtParseError),
120
121    //KeyMismatch(bitcoin::secp256k1::PublicKey, bitcoin::secp256k1::PublicKey),
122    //MissingInputUTXO(usize),
123    //InvalidAddressNetwork(Address),
124    //DifferentTransactions,
125    //DifferentDescriptorStructure,
126    //Uncapable(crate::blockchain::Capability),
127    //MissingCachedAddresses,
128    /// [`crate::blockchain::WalletSync`] sync attempt failed due to missing scripts in cache which
129    /// are needed to satisfy `stop_gap`.
130    MissingCachedScripts(MissingCachedScripts),
131
132    #[cfg(feature = "electrum")]
133    /// Electrum client error
134    Electrum(electrum_client::Error),
135    #[cfg(feature = "esplora")]
136    /// Esplora client error
137    Esplora(Box<crate::blockchain::esplora::EsploraError>),
138    #[cfg(feature = "compact_filters")]
139    /// Compact filters client error)
140    CompactFilters(crate::blockchain::compact_filters::CompactFiltersError),
141    #[cfg(feature = "key-value-db")]
142    /// Sled database error
143    Sled(sled::Error),
144    #[cfg(feature = "rpc")]
145    /// Rpc client error
146    Rpc(bitcoincore_rpc::Error),
147    #[cfg(feature = "sqlite")]
148    /// Rusqlite client error
149    Rusqlite(rusqlite::Error),
150}
151
152/// Errors returned by miniscript when updating inconsistent PSBTs
153#[derive(Debug, Clone)]
154pub enum MiniscriptPsbtError {
155    Conversion(miniscript::descriptor::ConversionError),
156    UtxoUpdate(miniscript::psbt::UtxoUpdateError),
157    OutputUpdate(miniscript::psbt::OutputUpdateError),
158}
159
160impl fmt::Display for MiniscriptPsbtError {
161    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
162        match self {
163            Self::Conversion(err) => write!(f, "Conversion error: {}", err),
164            Self::UtxoUpdate(err) => write!(f, "UTXO update error: {}", err),
165            Self::OutputUpdate(err) => write!(f, "Output update error: {}", err),
166        }
167    }
168}
169
170impl std::error::Error for MiniscriptPsbtError {}
171
172/// Represents the last failed [`crate::blockchain::WalletSync`] sync attempt in which we were short
173/// on cached `scriptPubKey`s.
174#[derive(Debug)]
175pub struct MissingCachedScripts {
176    /// Number of scripts in which txs were requested during last request.
177    pub last_count: usize,
178    /// Minimum number of scripts to cache more of in order to satisfy `stop_gap`.
179    pub missing_count: usize,
180}
181
182impl fmt::Display for Error {
183    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
184        match self {
185            Self::InvalidU32Bytes(_) => write!(
186                f,
187                "Wrong number of bytes found when trying to convert to u32"
188            ),
189            Self::Generic(err) => write!(f, "Generic error: {}", err),
190            Self::ScriptDoesntHaveAddressForm => write!(f, "Script doesn't have address form"),
191            Self::NoRecipients => write!(f, "Cannot build tx without recipients"),
192            Self::NoUtxosSelected => write!(f, "No UTXO selected"),
193            Self::OutputBelowDustLimit(limit) => {
194                write!(f, "Output below the dust limit: {}", limit)
195            }
196            Self::InsufficientFunds { needed, available } => write!(
197                f,
198                "Insufficient funds: {} sat available of {} sat needed",
199                available, needed
200            ),
201            Self::BnBTotalTriesExceeded => {
202                write!(f, "Branch and bound coin selection: total tries exceeded")
203            }
204            Self::BnBNoExactMatch => write!(f, "Branch and bound coin selection: not exact match"),
205            Self::UnknownUtxo => write!(f, "UTXO not found in the internal database"),
206            Self::TransactionNotFound => {
207                write!(f, "Transaction not found in the internal database")
208            }
209            Self::TransactionConfirmed => write!(f, "Transaction already confirmed"),
210            Self::IrreplaceableTransaction => write!(f, "Transaction can't be replaced"),
211            Self::FeeRateTooLow { required } => write!(
212                f,
213                "Fee rate too low: required {} sat/vbyte",
214                required.as_sat_per_vb()
215            ),
216            Self::FeeTooLow { required } => write!(f, "Fee to low: required {} sat", required),
217            Self::FeeRateUnavailable => write!(f, "Fee rate unavailable"),
218            Self::MissingKeyOrigin(err) => write!(f, "Missing key origin: {}", err),
219            Self::Key(err) => write!(f, "Key error: {}", err),
220            Self::ChecksumMismatch => write!(f, "Descriptor checksum mismatch"),
221            Self::SpendingPolicyRequired(keychain_kind) => {
222                write!(f, "Spending policy required: {:?}", keychain_kind)
223            }
224            Self::InvalidPolicyPathError(err) => write!(f, "Invalid policy path: {}", err),
225            Self::Signer(err) => write!(f, "Signer error: {}", err),
226            Self::InvalidNetwork { requested, found } => write!(
227                f,
228                "Invalid network: requested {} but found {}",
229                requested, found
230            ),
231            #[cfg(feature = "verify")]
232            Self::Verification(err) => write!(f, "Transaction verification error: {}", err),
233            Self::InvalidProgressValue(progress) => {
234                write!(f, "Invalid progress value: {}", progress)
235            }
236            Self::ProgressUpdateError => write!(
237                f,
238                "Progress update error (maybe the channel has been closed)"
239            ),
240            Self::InvalidOutpoint(outpoint) => write!(
241                f,
242                "Requested outpoint doesn't exist in the tx: {}",
243                outpoint
244            ),
245            Self::Descriptor(err) => write!(f, "Descriptor error: {}", err),
246            Self::Encode(err) => write!(f, "Encoding error: {}", err),
247            Self::Miniscript(err) => write!(f, "Miniscript error: {}", err),
248            Self::MiniscriptPsbt(err) => write!(f, "Miniscript PSBT error: {}", err),
249            Self::Bip32(err) => write!(f, "BIP32 error: {}", err),
250            Self::Secp256k1(err) => write!(f, "Secp256k1 error: {}", err),
251            Self::Json(err) => write!(f, "Serialize/Deserialize JSON error: {}", err),
252            Self::Hex(err) => write!(f, "Hex decoding error: {}", err),
253            Self::Psbt(err) => write!(f, "PSBT error: {}", err),
254            Self::PsbtParse(err) => write!(f, "Impossible to parse PSBT: {}", err),
255            Self::MissingCachedScripts(missing_cached_scripts) => {
256                write!(f, "Missing cached scripts: {:?}", missing_cached_scripts)
257            }
258            #[cfg(feature = "electrum")]
259            Self::Electrum(err) => write!(f, "Electrum client error: {}", err),
260            #[cfg(feature = "esplora")]
261            Self::Esplora(err) => write!(f, "Esplora client error: {}", err),
262            #[cfg(feature = "compact_filters")]
263            Self::CompactFilters(err) => write!(f, "Compact filters client error: {}", err),
264            #[cfg(feature = "key-value-db")]
265            Self::Sled(err) => write!(f, "Sled database error: {}", err),
266            #[cfg(feature = "rpc")]
267            Self::Rpc(err) => write!(f, "RPC client error: {}", err),
268            #[cfg(feature = "sqlite")]
269            Self::Rusqlite(err) => write!(f, "SQLite error: {}", err),
270        }
271    }
272}
273
274impl std::error::Error for Error {}
275
276macro_rules! impl_error {
277    ( $from:ty, $to:ident ) => {
278        impl_error!($from, $to, Error);
279    };
280    ( $from:ty, $to:ident, $impl_for:ty ) => {
281        impl std::convert::From<$from> for $impl_for {
282            fn from(err: $from) -> Self {
283                <$impl_for>::$to(err)
284            }
285        }
286    };
287}
288
289impl_error!(descriptor::error::Error, Descriptor);
290impl_error!(descriptor::policy::PolicyError, InvalidPolicyPathError);
291impl_error!(wallet::signer::SignerError, Signer);
292
293impl From<crate::keys::KeyError> for Error {
294    fn from(key_error: crate::keys::KeyError) -> Error {
295        match key_error {
296            crate::keys::KeyError::Miniscript(inner) => Error::Miniscript(inner),
297            crate::keys::KeyError::Bip32(inner) => Error::Bip32(inner),
298            crate::keys::KeyError::InvalidChecksum => Error::ChecksumMismatch,
299            e => Error::Key(e),
300        }
301    }
302}
303
304impl_error!(bitcoin::consensus::encode::Error, Encode);
305impl_error!(miniscript::Error, Miniscript);
306impl_error!(MiniscriptPsbtError, MiniscriptPsbt);
307impl_error!(bitcoin::util::bip32::Error, Bip32);
308impl_error!(bitcoin::secp256k1::Error, Secp256k1);
309impl_error!(serde_json::Error, Json);
310impl_error!(bitcoin::hashes::hex::Error, Hex);
311impl_error!(bitcoin::util::psbt::Error, Psbt);
312impl_error!(bitcoin::util::psbt::PsbtParseError, PsbtParse);
313
314#[cfg(feature = "electrum")]
315impl_error!(electrum_client::Error, Electrum);
316#[cfg(feature = "key-value-db")]
317impl_error!(sled::Error, Sled);
318#[cfg(feature = "rpc")]
319impl_error!(bitcoincore_rpc::Error, Rpc);
320#[cfg(feature = "sqlite")]
321impl_error!(rusqlite::Error, Rusqlite);
322
323#[cfg(feature = "compact_filters")]
324impl From<crate::blockchain::compact_filters::CompactFiltersError> for Error {
325    fn from(other: crate::blockchain::compact_filters::CompactFiltersError) -> Self {
326        match other {
327            crate::blockchain::compact_filters::CompactFiltersError::Global(e) => *e,
328            err => Error::CompactFilters(err),
329        }
330    }
331}
332
333#[cfg(feature = "verify")]
334impl From<crate::wallet::verify::VerifyError> for Error {
335    fn from(other: crate::wallet::verify::VerifyError) -> Self {
336        match other {
337            crate::wallet::verify::VerifyError::Global(inner) => *inner,
338            err => Error::Verification(err),
339        }
340    }
341}
342
343#[cfg(feature = "esplora")]
344impl From<crate::blockchain::esplora::EsploraError> for Error {
345    fn from(other: crate::blockchain::esplora::EsploraError) -> Self {
346        Error::Esplora(Box::new(other))
347    }
348}