Skip to content

Commit a300c24

Browse files
committed
refactor(wallet)!: Use SignerError as error type for Wallet::sign() and Wallet::finalize_psbt()
refactor(wallet)!: Add SignerError::MiniscriptPsbt enum variant
1 parent 15b38c3 commit a300c24

File tree

6 files changed

+43
-44
lines changed

6 files changed

+43
-44
lines changed

crates/bdk/src/wallet/error.rs

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
use crate::descriptor::policy::PolicyError;
1515
use crate::descriptor::DescriptorError;
1616
use crate::wallet::coin_selection;
17-
use crate::{descriptor, wallet, FeeRate, KeychainKind};
17+
use crate::{descriptor, FeeRate, KeychainKind};
1818
use alloc::string::String;
1919
use bitcoin::{absolute, psbt, OutPoint, ScriptBuf, Sequence, Txid};
2020
use core::fmt;
@@ -291,29 +291,6 @@ impl fmt::Display for BuildFeeBumpError {
291291
#[cfg(feature = "std")]
292292
impl std::error::Error for BuildFeeBumpError {}
293293

294-
#[derive(Debug)]
295-
/// Error returned from [`Wallet::sign`]
296-
///
297-
/// [`Wallet::sign`]: wallet::Wallet::sign
298-
pub enum SignError {
299-
/// Signing error
300-
Signer(wallet::signer::SignerError),
301-
/// Miniscript PSBT error
302-
MiniscriptPsbt(MiniscriptPsbtError),
303-
}
304-
305-
impl fmt::Display for SignError {
306-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
307-
match self {
308-
Self::Signer(err) => write!(f, "Signer error: {}", err),
309-
Self::MiniscriptPsbt(err) => write!(f, "Miniscript PSBT error: {}", err),
310-
}
311-
}
312-
}
313-
314-
#[cfg(feature = "std")]
315-
impl std::error::Error for SignError {}
316-
317294
#[derive(Debug)]
318295
/// Error returned from [`TxBuilder::add_utxo`] and [`TxBuilder::add_utxos`]
319296
///
@@ -340,10 +317,9 @@ impl fmt::Display for AddUtxoError {
340317
impl std::error::Error for AddUtxoError {}
341318

342319
#[derive(Debug)]
343-
/// Error returned from [`TxBuilder::add_utxo`] and [`TxBuilder::add_utxos`]
320+
/// Error returned from [`TxBuilder::add_foreign_utxo`].
344321
///
345-
/// [`TxBuilder::add_utxo`]: wallet::tx_builder::TxBuilder::add_utxo
346-
/// [`TxBuilder::add_utxos`]: wallet::tx_builder::TxBuilder::add_utxos
322+
/// [`TxBuilder::add_foreign_utxo`]: wallet::tx_builder::TxBuilder::add_foreign_utxo
347323
pub enum AddForeignUtxoError {
348324
/// Foreign utxo outpoint txid does not match PSBT input txid
349325
InvalidTxid {

crates/bdk/src/wallet/mod.rs

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ use crate::psbt::PsbtUtils;
7474
use crate::signer::SignerError;
7575
use crate::types::*;
7676
use crate::wallet::coin_selection::Excess::{Change, NoChange};
77-
use crate::wallet::error::{BuildFeeBumpError, CreateTxError, MiniscriptPsbtError, SignError};
77+
use crate::wallet::error::{BuildFeeBumpError, CreateTxError, MiniscriptPsbtError};
7878

7979
const COINBASE_MATURITY: u32 = 100;
8080

@@ -1702,7 +1702,7 @@ impl<D> Wallet<D> {
17021702
/// # use bitcoin::*;
17031703
/// # use bdk::*;
17041704
/// # use bdk::wallet::ChangeSet;
1705-
/// # use bdk::wallet::error::{CreateTxError, SignError};
1705+
/// # use bdk::wallet::error::CreateTxError;
17061706
/// # use bdk_chain::PersistBackend;
17071707
/// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
17081708
/// # let mut wallet = doctest_wallet!();
@@ -1712,18 +1712,18 @@ impl<D> Wallet<D> {
17121712
/// builder.add_recipient(to_address.script_pubkey(), 50_000);
17131713
/// builder.finish()?
17141714
/// };
1715-
/// let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
1715+
/// let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
17161716
/// assert!(finalized, "we should have signed all the inputs");
17171717
/// # Ok::<(),anyhow::Error>(())
17181718
pub fn sign(
17191719
&self,
17201720
psbt: &mut psbt::PartiallySignedTransaction,
17211721
sign_options: SignOptions,
1722-
) -> Result<bool, SignError> {
1722+
) -> Result<bool, SignerError> {
17231723
// This adds all the PSBT metadata for the inputs, which will help us later figure out how
17241724
// to derive our keys
17251725
self.update_psbt_with_descriptor(psbt)
1726-
.map_err(SignError::MiniscriptPsbt)?;
1726+
.map_err(SignerError::MiniscriptPsbt)?;
17271727

17281728
// If we aren't allowed to use `witness_utxo`, ensure that every input (except p2tr and finalized ones)
17291729
// has the `non_witness_utxo`
@@ -1735,7 +1735,7 @@ impl<D> Wallet<D> {
17351735
.filter(|i| i.tap_internal_key.is_none() && i.tap_merkle_root.is_none())
17361736
.any(|i| i.non_witness_utxo.is_none())
17371737
{
1738-
return Err(SignError::Signer(SignerError::MissingNonWitnessUtxo));
1738+
return Err(SignerError::MissingNonWitnessUtxo);
17391739
}
17401740

17411741
// If the user hasn't explicitly opted-in, refuse to sign the transaction unless every input
@@ -1748,7 +1748,7 @@ impl<D> Wallet<D> {
17481748
|| i.sighash_type == Some(TapSighashType::Default.into())
17491749
})
17501750
{
1751-
return Err(SignError::Signer(SignerError::NonStandardSighash));
1751+
return Err(SignerError::NonStandardSighash);
17521752
}
17531753

17541754
for signer in self
@@ -1757,9 +1757,7 @@ impl<D> Wallet<D> {
17571757
.iter()
17581758
.chain(self.change_signers.signers().iter())
17591759
{
1760-
signer
1761-
.sign_transaction(psbt, &sign_options, &self.secp)
1762-
.map_err(SignError::Signer)?;
1760+
signer.sign_transaction(psbt, &sign_options, &self.secp)?;
17631761
}
17641762

17651763
// attempt to finalize
@@ -1813,7 +1811,7 @@ impl<D> Wallet<D> {
18131811
let psbt_input = &psbt
18141812
.inputs
18151813
.get(n)
1816-
.ok_or(SignerError::Signer(SignerError::InputIndexOutOfRange))?;
1814+
.ok_or(SignerError::InputIndexOutOfRange)?;
18171815
if psbt_input.final_script_sig.is_some() || psbt_input.final_script_witness.is_some() {
18181816
continue;
18191817
}

crates/bdk/src/wallet/signer.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ use miniscript::{Legacy, Segwitv0, SigType, Tap, ToPublicKey};
103103
use super::utils::SecpCtx;
104104
use crate::descriptor::{DescriptorMeta, XKeyUtils};
105105
use crate::psbt::PsbtUtils;
106+
use crate::wallet::error::MiniscriptPsbtError;
106107

107108
/// Identifier of a signer in the `SignersContainers`. Used as a key to find the right signer among
108109
/// multiple of them
@@ -159,6 +160,8 @@ pub enum SignerError {
159160
InvalidSighash,
160161
/// Error while computing the hash to sign
161162
SighashError(sighash::Error),
163+
/// Miniscript PSBT error
164+
MiniscriptPsbt(MiniscriptPsbtError),
162165
/// Error while signing using hardware wallets
163166
#[cfg(feature = "hardware-signer")]
164167
HWIError(hwi::error::Error),
@@ -192,6 +195,7 @@ impl fmt::Display for SignerError {
192195
Self::NonStandardSighash => write!(f, "The psbt contains a non standard sighash"),
193196
Self::InvalidSighash => write!(f, "Invalid SIGHASH for the signing context in use"),
194197
Self::SighashError(err) => write!(f, "Error while computing the hash to sign: {}", err),
198+
Self::MiniscriptPsbt(err) => write!(f, "Miniscript PSBT error: {}", err),
195199
#[cfg(feature = "hardware-signer")]
196200
Self::HWIError(err) => write!(f, "Error while signing using hardware wallets: {}", err),
197201
}

crates/bdk/src/wallet/tx_builder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,7 @@ impl<'a, D, Cs: CoinSelectionAlgorithm, Ctx: TxBuilderContext> TxBuilder<'a, D,
551551

552552
/// Finish building the transaction.
553553
///
554-
/// Returns the [`BIP174`] "PSBT" and summary details about the transaction.
554+
/// Returns a new [`Psbt`] per [BIP174].
555555
///
556556
/// [`BIP174`]: https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki
557557
pub fn finish(self) -> Result<Psbt, CreateTxError<D::WriteError>>

crates/bdk/tests/wallet.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use bdk::descriptor::calc_checksum;
55
use bdk::psbt::PsbtUtils;
66
use bdk::signer::{SignOptions, SignerError};
77
use bdk::wallet::coin_selection::{self, LargestFirstCoinSelection};
8-
use bdk::wallet::error::{AddForeignUtxoError, CreateTxError, SignError};
8+
use bdk::wallet::error::{AddForeignUtxoError, CreateTxError};
99
use bdk::wallet::AddressIndex::*;
1010
use bdk::wallet::{AddressIndex, AddressInfo, Balance, Wallet};
1111
use bdk::{FeeRate, KeychainKind};
@@ -2524,7 +2524,7 @@ fn test_sign_nonstandard_sighash() {
25242524
);
25252525
assert_matches!(
25262526
result,
2527-
Err(SignError::Signer(SignerError::NonStandardSighash)),
2527+
Err(SignerError::NonStandardSighash),
25282528
"Signing failed with the wrong error type"
25292529
);
25302530

@@ -2941,7 +2941,7 @@ fn test_taproot_sign_missing_witness_utxo() {
29412941
);
29422942
assert_matches!(
29432943
result,
2944-
Err(SignError::Signer(SignerError::MissingWitnessUtxo)),
2944+
Err(SignerError::MissingWitnessUtxo),
29452945
"Signing should have failed with the correct error because the witness_utxo is missing"
29462946
);
29472947

@@ -3282,7 +3282,7 @@ fn test_taproot_sign_non_default_sighash() {
32823282
);
32833283
assert_matches!(
32843284
result,
3285-
Err(SignError::Signer(SignerError::NonStandardSighash)),
3285+
Err(SignerError::NonStandardSighash),
32863286
"Signing failed with the wrong error type"
32873287
);
32883288

@@ -3300,7 +3300,7 @@ fn test_taproot_sign_non_default_sighash() {
33003300
);
33013301
assert_matches!(
33023302
result,
3303-
Err(SignError::Signer(SignerError::MissingWitnessUtxo)),
3303+
Err(SignerError::MissingWitnessUtxo),
33043304
"Signing failed with the wrong error type"
33053305
);
33063306

crates/chain/src/tx_graph.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ use crate::{
5757
use alloc::collections::vec_deque::VecDeque;
5858
use alloc::vec::Vec;
5959
use bitcoin::{OutPoint, Script, Transaction, TxOut, Txid};
60+
use core::fmt::{self, Formatter};
6061
use core::{
6162
convert::Infallible,
6263
ops::{Deref, RangeInclusive},
@@ -145,6 +146,26 @@ pub enum CalculateFeeError {
145146
NegativeFee(i64),
146147
}
147148

149+
impl fmt::Display for CalculateFeeError {
150+
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
151+
match self {
152+
CalculateFeeError::MissingTxOut(outpoints) => write!(
153+
f,
154+
"missing `TxOut` for one or more of the inputs of the tx: {:?}",
155+
outpoints
156+
),
157+
CalculateFeeError::NegativeFee(fee) => write!(
158+
f,
159+
"transaction is invalid according to the graph and has negative fee: {}",
160+
fee
161+
),
162+
}
163+
}
164+
}
165+
166+
#[cfg(feature = "std")]
167+
impl std::error::Error for CalculateFeeError {}
168+
148169
impl<A> TxGraph<A> {
149170
/// Iterate over all tx outputs known by [`TxGraph`].
150171
///

0 commit comments

Comments
 (0)