1use std::fmt;
13
14use crate::bitcoin::Network;
15use crate::{descriptor, wallet};
16use bitcoin::{OutPoint, Txid};
17
18#[derive(Debug)]
20pub enum Error {
21 InvalidU32Bytes(Vec<u8>),
23 Generic(String),
25 ScriptDoesntHaveAddressForm,
27 NoRecipients,
29 NoUtxosSelected,
31 OutputBelowDustLimit(usize),
33 InsufficientFunds {
35 needed: u64,
37 available: u64,
39 },
40 BnBTotalTriesExceeded,
43 BnBNoExactMatch,
46 UnknownUtxo,
48 TransactionNotFound,
50 TransactionConfirmed,
52 IrreplaceableTransaction,
54 FeeRateTooLow {
56 required: crate::types::FeeRate,
58 },
59 FeeTooLow {
61 required: u64,
63 },
64 FeeRateUnavailable,
66 MissingKeyOrigin(String),
72 Key(crate::keys::KeyError),
74 ChecksumMismatch,
76 SpendingPolicyRequired(crate::types::KeychainKind),
78 InvalidPolicyPathError(crate::descriptor::policy::PolicyError),
80 Signer(crate::wallet::signer::SignerError),
82 InvalidNetwork {
84 requested: Network,
86 found: Network,
88 },
89 #[cfg(feature = "verify")]
90 Verification(crate::wallet::verify::VerifyError),
92
93 InvalidProgressValue(f32),
95 ProgressUpdateError,
97 InvalidOutpoint(OutPoint),
99
100 Descriptor(crate::descriptor::error::Error),
102 Encode(bitcoin::consensus::encode::Error),
104 Miniscript(miniscript::Error),
106 MiniscriptPsbt(MiniscriptPsbtError),
108 Bip32(bitcoin::util::bip32::Error),
110 Secp256k1(bitcoin::secp256k1::Error),
112 Json(serde_json::Error),
114 Hex(bitcoin::hashes::hex::Error),
116 Psbt(bitcoin::util::psbt::Error),
118 PsbtParse(bitcoin::util::psbt::PsbtParseError),
120
121 MissingCachedScripts(MissingCachedScripts),
131
132 #[cfg(feature = "electrum")]
133 Electrum(electrum_client::Error),
135 #[cfg(feature = "esplora")]
136 Esplora(Box<crate::blockchain::esplora::EsploraError>),
138 #[cfg(feature = "compact_filters")]
139 CompactFilters(crate::blockchain::compact_filters::CompactFiltersError),
141 #[cfg(feature = "key-value-db")]
142 Sled(sled::Error),
144 #[cfg(feature = "rpc")]
145 Rpc(bitcoincore_rpc::Error),
147 #[cfg(feature = "sqlite")]
148 Rusqlite(rusqlite::Error),
150}
151
152#[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#[derive(Debug)]
175pub struct MissingCachedScripts {
176 pub last_count: usize,
178 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}