• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

bitcoindevkit / bdk / 5834188079

pending completion
5834188079

Pull #1071

github

web-flow
Merge 68b42331c into 0ba6bbe11
Pull Request #1071: Update rust bitcoin (BDK 0.28)

563 of 563 new or added lines in 28 files covered. (100.0%)

14625 of 18342 relevant lines covered (79.74%)

9267.73 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

3.92
/src/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

12
use std::fmt;
13

14
use crate::bitcoin::Network;
15
use crate::{descriptor, wallet};
16
use bitcoin::{OutPoint, Txid};
17

18
/// Errors that can be thrown by the [`Wallet`](crate::wallet::Wallet)
19
#[derive(Debug)]
66✔
20
pub 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
    /// The address requested comes from an hardened index
90
    HardenedIndex,
91
    #[cfg(feature = "verify")]
92
    /// Transaction verification error
93
    Verification(crate::wallet::verify::VerifyError),
94

95
    /// Progress value must be between `0.0` (included) and `100.0` (included)
96
    InvalidProgressValue(f32),
97
    /// Progress update error (maybe the channel has been closed)
98
    ProgressUpdateError,
99
    /// Requested outpoint doesn't exist in the tx (vout greater than available outputs)
100
    InvalidOutpoint(OutPoint),
101

102
    /// Error related to the parsing and usage of descriptors
103
    Descriptor(crate::descriptor::error::Error),
104
    /// Encoding error
105
    Encode(bitcoin::consensus::encode::Error),
106
    /// Miniscript error
107
    Miniscript(miniscript::Error),
108
    /// Miniscript PSBT error
109
    MiniscriptPsbt(MiniscriptPsbtError),
110
    /// BIP32 error
111
    Bip32(bitcoin::bip32::Error),
112
    /// A secp256k1 error
113
    Secp256k1(bitcoin::secp256k1::Error),
114
    /// Error serializing or deserializing JSON data
115
    Json(serde_json::Error),
116
    /// Hex decoding error
117
    Hex(bitcoin::hashes::hex::Error),
118
    /// Partially signed bitcoin transaction error
119
    Psbt(bitcoin::psbt::Error),
120
    /// Partially signed bitcoin transaction parse error
121
    PsbtParse(bitcoin::psbt::PsbtParseError),
122

123
    //KeyMismatch(bitcoin::secp256k1::PublicKey, bitcoin::secp256k1::PublicKey),
124
    //MissingInputUTXO(usize),
125
    //InvalidAddressNetwork(Address),
126
    //DifferentTransactions,
127
    //DifferentDescriptorStructure,
128
    //Uncapable(crate::blockchain::Capability),
129
    //MissingCachedAddresses,
130
    /// [`crate::blockchain::WalletSync`] sync attempt failed due to missing scripts in cache which
131
    /// are needed to satisfy `stop_gap`.
132
    MissingCachedScripts(MissingCachedScripts),
133

134
    #[cfg(feature = "electrum")]
135
    /// Electrum client error
136
    Electrum(electrum_client::Error),
137
    #[cfg(feature = "esplora")]
138
    /// Esplora client error
139
    Esplora(Box<crate::blockchain::esplora::EsploraError>),
140
    #[cfg(feature = "compact_filters")]
141
    /// Compact filters client error)
142
    CompactFilters(crate::blockchain::compact_filters::CompactFiltersError),
143
    #[cfg(feature = "key-value-db")]
144
    /// Sled database error
145
    Sled(sled::Error),
146
    #[cfg(feature = "rpc")]
147
    /// Rpc client error
148
    Rpc(bitcoincore_rpc::Error),
149
    #[cfg(feature = "sqlite")]
150
    /// Rusqlite client error
151
    Rusqlite(rusqlite::Error),
152
}
153

154
/// Errors returned by miniscript when updating inconsistent PSBTs
155
#[derive(Debug, Clone)]
×
156
pub enum MiniscriptPsbtError {
157
    Conversion(miniscript::descriptor::ConversionError),
158
    UtxoUpdate(miniscript::psbt::UtxoUpdateError),
159
    OutputUpdate(miniscript::psbt::OutputUpdateError),
160
}
161

162
impl fmt::Display for MiniscriptPsbtError {
163
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
×
164
        match self {
×
165
            Self::Conversion(err) => write!(f, "Conversion error: {}", err),
×
166
            Self::UtxoUpdate(err) => write!(f, "UTXO update error: {}", err),
×
167
            Self::OutputUpdate(err) => write!(f, "Output update error: {}", err),
×
168
        }
169
    }
×
170
}
171

172
impl std::error::Error for MiniscriptPsbtError {}
173

174
/// Represents the last failed [`crate::blockchain::WalletSync`] sync attempt in which we were short
175
/// on cached `scriptPubKey`s.
176
#[derive(Debug)]
×
177
pub struct MissingCachedScripts {
178
    /// Number of scripts in which txs were requested during last request.
179
    pub last_count: usize,
180
    /// Minimum number of scripts to cache more of in order to satisfy `stop_gap`.
181
    pub missing_count: usize,
182
}
183

184
impl fmt::Display for Error {
185
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
×
186
        match self {
×
187
            Self::InvalidU32Bytes(_) => write!(
×
188
                f,
×
189
                "Wrong number of bytes found when trying to convert to u32"
×
190
            ),
×
191
            Self::Generic(err) => write!(f, "Generic error: {}", err),
×
192
            Self::ScriptDoesntHaveAddressForm => write!(f, "Script doesn't have address form"),
×
193
            Self::NoRecipients => write!(f, "Cannot build tx without recipients"),
×
194
            Self::NoUtxosSelected => write!(f, "No UTXO selected"),
×
195
            Self::OutputBelowDustLimit(limit) => {
×
196
                write!(f, "Output below the dust limit: {}", limit)
×
197
            }
198
            Self::InsufficientFunds { needed, available } => write!(
×
199
                f,
×
200
                "Insufficient funds: {} sat available of {} sat needed",
×
201
                available, needed
×
202
            ),
×
203
            Self::BnBTotalTriesExceeded => {
204
                write!(f, "Branch and bound coin selection: total tries exceeded")
×
205
            }
206
            Self::BnBNoExactMatch => write!(f, "Branch and bound coin selection: not exact match"),
×
207
            Self::UnknownUtxo => write!(f, "UTXO not found in the internal database"),
×
208
            Self::TransactionNotFound => {
209
                write!(f, "Transaction not found in the internal database")
×
210
            }
211
            Self::TransactionConfirmed => write!(f, "Transaction already confirmed"),
×
212
            Self::IrreplaceableTransaction => write!(f, "Transaction can't be replaced"),
×
213
            Self::FeeRateTooLow { required } => write!(
×
214
                f,
×
215
                "Fee rate too low: required {} sat/vbyte",
×
216
                required.as_sat_per_vb()
×
217
            ),
×
218
            Self::FeeTooLow { required } => write!(f, "Fee to low: required {} sat", required),
×
219
            Self::FeeRateUnavailable => write!(f, "Fee rate unavailable"),
×
220
            Self::MissingKeyOrigin(err) => write!(f, "Missing key origin: {}", err),
×
221
            Self::Key(err) => write!(f, "Key error: {}", err),
×
222
            Self::ChecksumMismatch => write!(f, "Descriptor checksum mismatch"),
×
223
            Self::SpendingPolicyRequired(keychain_kind) => {
×
224
                write!(f, "Spending policy required: {:?}", keychain_kind)
×
225
            }
226
            Self::InvalidPolicyPathError(err) => write!(f, "Invalid policy path: {}", err),
×
227
            Self::Signer(err) => write!(f, "Signer error: {}", err),
×
228
            Self::InvalidNetwork { requested, found } => write!(
×
229
                f,
×
230
                "Invalid network: requested {} but found {}",
×
231
                requested, found
×
232
            ),
×
233
            Self::HardenedIndex => write!(f, "Requested address from an hardened index"),
×
234
            #[cfg(feature = "verify")]
235
            Self::Verification(err) => write!(f, "Transaction verification error: {}", err),
×
236
            Self::InvalidProgressValue(progress) => {
×
237
                write!(f, "Invalid progress value: {}", progress)
×
238
            }
239
            Self::ProgressUpdateError => write!(
×
240
                f,
×
241
                "Progress update error (maybe the channel has been closed)"
×
242
            ),
×
243
            Self::InvalidOutpoint(outpoint) => write!(
×
244
                f,
×
245
                "Requested outpoint doesn't exist in the tx: {}",
×
246
                outpoint
×
247
            ),
×
248
            Self::Descriptor(err) => write!(f, "Descriptor error: {}", err),
×
249
            Self::Encode(err) => write!(f, "Encoding error: {}", err),
×
250
            Self::Miniscript(err) => write!(f, "Miniscript error: {}", err),
×
251
            Self::MiniscriptPsbt(err) => write!(f, "Miniscript PSBT error: {}", err),
×
252
            Self::Bip32(err) => write!(f, "BIP32 error: {}", err),
×
253
            Self::Secp256k1(err) => write!(f, "Secp256k1 error: {}", err),
×
254
            Self::Json(err) => write!(f, "Serialize/Deserialize JSON error: {}", err),
×
255
            Self::Hex(err) => write!(f, "Hex decoding error: {}", err),
×
256
            Self::Psbt(err) => write!(f, "PSBT error: {}", err),
×
257
            Self::PsbtParse(err) => write!(f, "Impossible to parse PSBT: {}", err),
×
258
            Self::MissingCachedScripts(missing_cached_scripts) => {
×
259
                write!(f, "Missing cached scripts: {:?}", missing_cached_scripts)
×
260
            }
261
            #[cfg(feature = "electrum")]
262
            Self::Electrum(err) => write!(f, "Electrum client error: {}", err),
×
263
            #[cfg(feature = "esplora")]
264
            Self::Esplora(err) => write!(f, "Esplora client error: {}", err),
265
            #[cfg(feature = "compact_filters")]
266
            Self::CompactFilters(err) => write!(f, "Compact filters client error: {}", err),
×
267
            #[cfg(feature = "key-value-db")]
268
            Self::Sled(err) => write!(f, "Sled database error: {}", err),
×
269
            #[cfg(feature = "rpc")]
270
            Self::Rpc(err) => write!(f, "RPC client error: {}", err),
×
271
            #[cfg(feature = "sqlite")]
272
            Self::Rusqlite(err) => write!(f, "SQLite error: {}", err),
×
273
        }
274
    }
×
275
}
276

277
impl std::error::Error for Error {}
278

279
macro_rules! impl_error {
280
    ( $from:ty, $to:ident ) => {
281
        impl_error!($from, $to, Error);
282
    };
283
    ( $from:ty, $to:ident, $impl_for:ty ) => {
284
        impl std::convert::From<$from> for $impl_for {
285
            fn from(err: $from) -> Self {
18✔
286
                <$impl_for>::$to(err)
18✔
287
            }
18✔
288
        }
289
    };
290
}
291

292
impl_error!(descriptor::error::Error, Descriptor);
293
impl_error!(descriptor::policy::PolicyError, InvalidPolicyPathError);
294
impl_error!(wallet::signer::SignerError, Signer);
295

296
impl From<crate::keys::KeyError> for Error {
297
    fn from(key_error: crate::keys::KeyError) -> Error {
×
298
        match key_error {
×
299
            crate::keys::KeyError::Miniscript(inner) => Error::Miniscript(inner),
×
300
            crate::keys::KeyError::Bip32(inner) => Error::Bip32(inner),
×
301
            crate::keys::KeyError::InvalidChecksum => Error::ChecksumMismatch,
×
302
            e => Error::Key(e),
×
303
        }
304
    }
×
305
}
306

307
impl_error!(bitcoin::consensus::encode::Error, Encode);
308
impl_error!(miniscript::Error, Miniscript);
309
impl_error!(MiniscriptPsbtError, MiniscriptPsbt);
310
impl_error!(bitcoin::bip32::Error, Bip32);
311
impl_error!(bitcoin::secp256k1::Error, Secp256k1);
312
impl_error!(serde_json::Error, Json);
313
impl_error!(bitcoin::hashes::hex::Error, Hex);
314
impl_error!(bitcoin::psbt::Error, Psbt);
315
impl_error!(bitcoin::psbt::PsbtParseError, PsbtParse);
316

317
#[cfg(feature = "electrum")]
318
impl_error!(electrum_client::Error, Electrum);
319
#[cfg(feature = "key-value-db")]
320
impl_error!(sled::Error, Sled);
321
#[cfg(feature = "rpc")]
322
impl_error!(bitcoincore_rpc::Error, Rpc);
323
#[cfg(feature = "sqlite")]
324
impl_error!(rusqlite::Error, Rusqlite);
325

326
#[cfg(feature = "compact_filters")]
327
impl From<crate::blockchain::compact_filters::CompactFiltersError> for Error {
328
    fn from(other: crate::blockchain::compact_filters::CompactFiltersError) -> Self {
×
329
        match other {
×
330
            crate::blockchain::compact_filters::CompactFiltersError::Global(e) => *e,
×
331
            err => Error::CompactFilters(err),
×
332
        }
333
    }
×
334
}
335

336
#[cfg(feature = "verify")]
337
impl From<crate::wallet::verify::VerifyError> for Error {
338
    fn from(other: crate::wallet::verify::VerifyError) -> Self {
×
339
        match other {
×
340
            crate::wallet::verify::VerifyError::Global(inner) => *inner,
×
341
            err => Error::Verification(err),
×
342
        }
343
    }
×
344
}
345

346
#[cfg(feature = "esplora")]
347
impl From<crate::blockchain::esplora::EsploraError> for Error {
348
    fn from(other: crate::blockchain::esplora::EsploraError) -> Self {
349
        Error::Esplora(Box::new(other))
350
    }
351
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc