diff --git a/crates/bdk/src/wallet/error.rs b/crates/bdk/src/wallet/error.rs index db58fef06f..245969eaaf 100644 --- a/crates/bdk/src/wallet/error.rs +++ b/crates/bdk/src/wallet/error.rs @@ -16,6 +16,7 @@ use crate::descriptor::DescriptorError; use crate::wallet::coin_selection; use crate::{descriptor, FeeRate, KeychainKind}; use alloc::string::String; +use bdk_chain::keychain::AddKeychainError; use bitcoin::{absolute, psbt, OutPoint, Sequence, Txid}; use core::fmt; @@ -290,3 +291,26 @@ impl fmt::Display for BuildFeeBumpError { #[cfg(feature = "std")] impl std::error::Error for BuildFeeBumpError {} + +/// The keychain related errors type when creating or loading a [`Wallet`]. +/// +/// [`Wallet`]: crate::wallet::Wallet +#[derive(Debug)] +pub enum KeychainError { + /// There was problem with the passed-in descriptor(s). + Descriptor(DescriptorError), + /// There was an error adding the keychain. + AddKeyChain(AddKeychainError), +} + +impl fmt::Display for KeychainError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + KeychainError::Descriptor(e) => e.fmt(f), + KeychainError::AddKeyChain(e) => e.fmt(f), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for KeychainError {} diff --git a/crates/bdk/src/wallet/mod.rs b/crates/bdk/src/wallet/mod.rs index 7fe8dd4064..26be77559a 100644 --- a/crates/bdk/src/wallet/mod.rs +++ b/crates/bdk/src/wallet/mod.rs @@ -69,7 +69,7 @@ use crate::psbt::PsbtUtils; use crate::signer::SignerError; use crate::types::*; use crate::wallet::coin_selection::Excess::{Change, NoChange}; -use crate::wallet::error::{BuildFeeBumpError, CreateTxError, MiniscriptPsbtError}; +use crate::wallet::error::{BuildFeeBumpError, CreateTxError, KeychainError, MiniscriptPsbtError}; const COINBASE_MATURITY: u32 = 100; @@ -233,10 +233,10 @@ impl Wallet { descriptor: E, change_descriptor: Option, network: Network, - ) -> Result { + ) -> Result { Self::new(descriptor, change_descriptor, (), network).map_err(|e| match e { NewError::NonEmptyDatabase => unreachable!("mock-database cannot have data"), - NewError::Descriptor(e) => e, + NewError::KeychainError(e) => e, NewError::Write(_) => unreachable!("mock-write must always succeed"), }) } @@ -247,11 +247,11 @@ impl Wallet { change_descriptor: Option, network: Network, genesis_hash: BlockHash, - ) -> Result { + ) -> Result { Self::new_with_genesis_hash(descriptor, change_descriptor, (), network, genesis_hash) .map_err(|e| match e { NewError::NonEmptyDatabase => unreachable!("mock-database cannot have data"), - NewError::Descriptor(e) => e, + NewError::KeychainError(e) => e, NewError::Write(_) => unreachable!("mock-write must always succeed"), }) } @@ -300,8 +300,8 @@ where pub enum NewError { /// Database already has data. NonEmptyDatabase, - /// There was problem with the passed-in descriptor(s). - Descriptor(crate::descriptor::DescriptorError), + /// There was problem with the passed-in descriptor or adding the keychain. + KeychainError(KeychainError), /// We were unable to write the wallet's data to the persistence backend. Write(W), } @@ -316,7 +316,7 @@ where f, "database already has data - use `load` or `new_or_load` methods instead" ), - NewError::Descriptor(e) => e.fmt(f), + NewError::KeychainError(e) => e.fmt(f), NewError::Write(e) => e.fmt(f), } } @@ -332,8 +332,8 @@ impl std::error::Error for NewError where W: core::fmt::Display + core::fm /// [`load`]: Wallet::load #[derive(Debug)] pub enum LoadError { - /// There was a problem with the passed-in descriptor(s). - Descriptor(crate::descriptor::DescriptorError), + /// There was problem with the passed-in descriptor or adding the keychain. + KeychainError(KeychainError), /// Loading data from the persistence backend failed. Load(L), /// Wallet not initialized, persistence backend is empty. @@ -350,7 +350,7 @@ where { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - LoadError::Descriptor(e) => e.fmt(f), + LoadError::KeychainError(e) => e.fmt(f), LoadError::Load(e) => e.fmt(f), LoadError::NotInitialized => { write!(f, "wallet is not initialized, persistence backend is empty") @@ -372,8 +372,8 @@ impl std::error::Error for LoadError where L: core::fmt::Display + core::f /// [`new_or_load_with_genesis_hash`]: Wallet::new_or_load_with_genesis_hash #[derive(Debug)] pub enum NewOrLoadError { - /// There is a problem with the passed-in descriptor. - Descriptor(crate::descriptor::DescriptorError), + /// There was problem with the passed-in descriptor or adding the keychain. + KeychainError(KeychainError), /// Writing to the persistence backend failed. Write(W), /// Loading from the persistence backend failed. @@ -403,7 +403,7 @@ where { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - NewOrLoadError::Descriptor(e) => e.fmt(f), + NewOrLoadError::KeychainError(e) => e.fmt(f), NewOrLoadError::Write(e) => write!(f, "failed to write to persistence: {}", e), NewOrLoadError::Load(e) => write!(f, "failed to load from persistence: {}", e), NewOrLoadError::NotInitialized => { @@ -529,7 +529,7 @@ impl Wallet { let (signers, change_signers) = create_signers(&mut index, &secp, descriptor, change_descriptor, network) - .map_err(NewError::Descriptor)?; + .map_err(NewError::KeychainError)?; let indexed_graph = IndexedTxGraph::new(index); @@ -585,7 +585,7 @@ impl Wallet { let (signers, change_signers) = create_signers(&mut index, &secp, descriptor, change_descriptor, network) - .map_err(LoadError::Descriptor)?; + .map_err(LoadError::KeychainError)?; let mut indexed_graph = IndexedTxGraph::new(index); indexed_graph.apply_changeset(changeset.indexed_tx_graph); @@ -647,7 +647,7 @@ impl Wallet { let wallet = Self::load_from_changeset(descriptor, change_descriptor, db, changeset) .map_err(|e| match e { - LoadError::Descriptor(e) => NewOrLoadError::Descriptor(e), + LoadError::KeychainError(e) => NewOrLoadError::KeychainError(e), LoadError::Load(e) => NewOrLoadError::Load(e), LoadError::NotInitialized => NewOrLoadError::NotInitialized, LoadError::MissingNetwork => { @@ -688,7 +688,7 @@ impl Wallet { NewError::NonEmptyDatabase => { unreachable!("database is already checked to have no data") } - NewError::Descriptor(e) => NewOrLoadError::Descriptor(e), + NewError::KeychainError(e) => NewOrLoadError::KeychainError(e), NewError::Write(e) => NewOrLoadError::Write(e), }), } @@ -2535,16 +2535,22 @@ fn create_signers( descriptor: E, change_descriptor: Option, network: Network, -) -> Result<(Arc, Arc), crate::descriptor::error::Error> { - let (descriptor, keymap) = into_wallet_descriptor_checked(descriptor, secp, network)?; +) -> Result<(Arc, Arc), KeychainError> { + let (descriptor, keymap) = into_wallet_descriptor_checked(descriptor, secp, network) + .map_err(KeychainError::Descriptor)?; let signers = Arc::new(SignersContainer::build(keymap, &descriptor, secp)); - index.add_keychain(KeychainKind::External, descriptor); + _ = index + .add_keychain(KeychainKind::External, descriptor) + .map_err(KeychainError::AddKeyChain)?; let change_signers = match change_descriptor { Some(descriptor) => { - let (descriptor, keymap) = into_wallet_descriptor_checked(descriptor, secp, network)?; + let (descriptor, keymap) = into_wallet_descriptor_checked(descriptor, secp, network) + .map_err(KeychainError::Descriptor)?; let signers = Arc::new(SignersContainer::build(keymap, &descriptor, secp)); - index.add_keychain(KeychainKind::Internal, descriptor); + _ = index + .add_keychain(KeychainKind::Internal, descriptor) + .map_err(KeychainError::AddKeyChain)?; signers } None => Arc::new(SignersContainer::new()),