test(wallet): ensure checks work when loading wallet
This commit is contained in:
		
							parent
							
								
									af4ee0fa4b
								
							
						
					
					
						commit
						3aed4cf179
					
				| @ -57,6 +57,7 @@ pub trait PersistAsyncWith<Db>: Sized { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// Represents a persisted `T`.
 | /// Represents a persisted `T`.
 | ||||||
|  | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] | ||||||
| pub struct Persisted<T> { | pub struct Persisted<T> { | ||||||
|     inner: T, |     inner: T, | ||||||
| } | } | ||||||
|  | |||||||
| @ -13,7 +13,7 @@ | |||||||
| use core::fmt; | use core::fmt; | ||||||
| 
 | 
 | ||||||
| /// Errors related to the parsing and usage of descriptors
 | /// Errors related to the parsing and usage of descriptors
 | ||||||
| #[derive(Debug)] | #[derive(Debug, PartialEq)] | ||||||
| pub enum Error { | pub enum Error { | ||||||
|     /// Invalid HD Key path, such as having a wildcard but a length != 1
 |     /// Invalid HD Key path, such as having a wildcard but a length != 1
 | ||||||
|     InvalidHdKeyPath, |     InvalidHdKeyPath, | ||||||
|  | |||||||
| @ -935,7 +935,7 @@ impl<Ctx: ScriptContext> IntoDescriptorKey<Ctx> for PrivateKey { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// Errors thrown while working with [`keys`](crate::keys)
 | /// Errors thrown while working with [`keys`](crate::keys)
 | ||||||
| #[derive(Debug)] | #[derive(Debug, PartialEq)] | ||||||
| pub enum KeyError { | pub enum KeyError { | ||||||
|     /// The key cannot exist in the given script context
 |     /// The key cannot exist in the given script context
 | ||||||
|     InvalidScriptContext, |     InvalidScriptContext, | ||||||
|  | |||||||
| @ -184,7 +184,7 @@ impl fmt::Display for AddressInfo { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// The error type when loading a [`Wallet`] from a [`ChangeSet`].
 | /// The error type when loading a [`Wallet`] from a [`ChangeSet`].
 | ||||||
| #[derive(Debug)] | #[derive(Debug, PartialEq)] | ||||||
| pub enum LoadError { | pub enum LoadError { | ||||||
|     /// There was a problem with the passed-in descriptor(s).
 |     /// There was a problem with the passed-in descriptor(s).
 | ||||||
|     Descriptor(crate::descriptor::DescriptorError), |     Descriptor(crate::descriptor::DescriptorError), | ||||||
| @ -216,7 +216,7 @@ impl fmt::Display for LoadError { | |||||||
| impl std::error::Error for LoadError {} | impl std::error::Error for LoadError {} | ||||||
| 
 | 
 | ||||||
| /// Represents a mismatch with what is loaded and what is expected from [`LoadParams`].
 | /// Represents a mismatch with what is loaded and what is expected from [`LoadParams`].
 | ||||||
| #[derive(Debug)] | #[derive(Debug, PartialEq)] | ||||||
| pub enum LoadMismatch { | pub enum LoadMismatch { | ||||||
|     /// Network does not match.
 |     /// Network does not match.
 | ||||||
|     Network { |     Network { | ||||||
| @ -243,6 +243,18 @@ pub enum LoadMismatch { | |||||||
|     }, |     }, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | impl From<LoadMismatch> for LoadError { | ||||||
|  |     fn from(mismatch: LoadMismatch) -> Self { | ||||||
|  |         Self::Mismatch(mismatch) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl<E> From<LoadMismatch> for LoadWithPersistError<E> { | ||||||
|  |     fn from(mismatch: LoadMismatch) -> Self { | ||||||
|  |         Self::InvalidChangeSet(LoadError::Mismatch(mismatch)) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /// An error that may occur when applying a block to [`Wallet`].
 | /// An error that may occur when applying a block to [`Wallet`].
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub enum ApplyBlockError { | pub enum ApplyBlockError { | ||||||
|  | |||||||
| @ -138,7 +138,7 @@ impl chain::PersistWith<bdk_file_store::Store<crate::ChangeSet>> for Wallet { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// Error type for [`PersistedWallet::load`].
 | /// Error type for [`PersistedWallet::load`].
 | ||||||
| #[derive(Debug)] | #[derive(Debug, PartialEq)] | ||||||
| pub enum LoadWithPersistError<E> { | pub enum LoadWithPersistError<E> { | ||||||
|     /// Error from persistence.
 |     /// Error from persistence.
 | ||||||
|     Persist(E), |     Persist(E), | ||||||
|  | |||||||
| @ -13,8 +13,9 @@ use bdk_wallet::error::CreateTxError; | |||||||
| use bdk_wallet::psbt::PsbtUtils; | use bdk_wallet::psbt::PsbtUtils; | ||||||
| use bdk_wallet::signer::{SignOptions, SignerError}; | use bdk_wallet::signer::{SignOptions, SignerError}; | ||||||
| use bdk_wallet::tx_builder::AddForeignUtxoError; | use bdk_wallet::tx_builder::AddForeignUtxoError; | ||||||
| use bdk_wallet::KeychainKind; |  | ||||||
| use bdk_wallet::{AddressInfo, Balance, CreateParams, LoadParams, Wallet}; | use bdk_wallet::{AddressInfo, Balance, CreateParams, LoadParams, Wallet}; | ||||||
|  | use bdk_wallet::{KeychainKind, LoadError, LoadMismatch, LoadWithPersistError}; | ||||||
|  | use bitcoin::constants::ChainHash; | ||||||
| use bitcoin::hashes::Hash; | use bitcoin::hashes::Hash; | ||||||
| use bitcoin::key::Secp256k1; | use bitcoin::key::Secp256k1; | ||||||
| use bitcoin::psbt; | use bitcoin::psbt; | ||||||
| @ -177,6 +178,93 @@ fn wallet_is_persisted() -> anyhow::Result<()> { | |||||||
|     Ok(()) |     Ok(()) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #[test] | ||||||
|  | fn wallet_load_checks() -> anyhow::Result<()> { | ||||||
|  |     fn run<Db, CreateDb, OpenDb, LoadDbError>( | ||||||
|  |         filename: &str, | ||||||
|  |         create_db: CreateDb, | ||||||
|  |         open_db: OpenDb, | ||||||
|  |     ) -> anyhow::Result<()> | ||||||
|  |     where | ||||||
|  |         CreateDb: Fn(&Path) -> anyhow::Result<Db>, | ||||||
|  |         OpenDb: Fn(&Path) -> anyhow::Result<Db>, | ||||||
|  |         Wallet: PersistWith< | ||||||
|  |             Db, | ||||||
|  |             CreateParams = CreateParams, | ||||||
|  |             LoadParams = LoadParams, | ||||||
|  |             LoadError = LoadWithPersistError<LoadDbError>, | ||||||
|  |         >, | ||||||
|  |         <Wallet as PersistWith<Db>>::CreateError: std::error::Error + Send + Sync + 'static, | ||||||
|  |         <Wallet as PersistWith<Db>>::LoadError: std::error::Error + Send + Sync + 'static, | ||||||
|  |         <Wallet as PersistWith<Db>>::PersistError: std::error::Error + Send + Sync + 'static, | ||||||
|  |     { | ||||||
|  |         let temp_dir = tempfile::tempdir().expect("must create tempdir"); | ||||||
|  |         let file_path = temp_dir.path().join(filename); | ||||||
|  |         let network = Network::Testnet; | ||||||
|  |         let (external_desc, internal_desc) = get_test_tr_single_sig_xprv_with_change_desc(); | ||||||
|  | 
 | ||||||
|  |         // create new wallet
 | ||||||
|  |         let _ = Wallet::create(external_desc, internal_desc) | ||||||
|  |             .network(network) | ||||||
|  |             .create_wallet(&mut create_db(&file_path)?)?; | ||||||
|  | 
 | ||||||
|  |         assert_matches!( | ||||||
|  |             Wallet::load() | ||||||
|  |                 .network(Network::Regtest) | ||||||
|  |                 .load_wallet(&mut open_db(&file_path)?), | ||||||
|  |             Err(LoadWithPersistError::InvalidChangeSet(LoadError::Mismatch( | ||||||
|  |                 LoadMismatch::Network { | ||||||
|  |                     loaded: Network::Testnet, | ||||||
|  |                     expected: Network::Regtest, | ||||||
|  |                 } | ||||||
|  |             ))), | ||||||
|  |             "unexpected network check result: Regtest (check) is not Testnet (loaded)", | ||||||
|  |         ); | ||||||
|  |         assert_matches!( | ||||||
|  |             Wallet::load() | ||||||
|  |                 .network(Network::Bitcoin) | ||||||
|  |                 .load_wallet(&mut open_db(&file_path)?), | ||||||
|  |             Err(LoadWithPersistError::InvalidChangeSet(LoadError::Mismatch( | ||||||
|  |                 LoadMismatch::Network { | ||||||
|  |                     loaded: Network::Testnet, | ||||||
|  |                     expected: Network::Bitcoin, | ||||||
|  |                 } | ||||||
|  |             ))), | ||||||
|  |             "unexpected network check result: Bitcoin (check) is not Testnet (loaded)", | ||||||
|  |         ); | ||||||
|  |         let mainnet_hash = BlockHash::from_byte_array(ChainHash::BITCOIN.to_bytes()); | ||||||
|  |         assert_matches!( | ||||||
|  |             Wallet::load().genesis_hash(mainnet_hash).load_wallet(&mut open_db(&file_path)?), | ||||||
|  |             Err(LoadWithPersistError::InvalidChangeSet(LoadError::Mismatch(LoadMismatch::Genesis { .. }))), | ||||||
|  |             "unexpected genesis hash check result: mainnet hash (check) is not testnet hash (loaded)", | ||||||
|  |         ); | ||||||
|  |         assert_matches!( | ||||||
|  |             Wallet::load() | ||||||
|  |                 .descriptors(internal_desc, external_desc) | ||||||
|  |                 .load_wallet(&mut open_db(&file_path)?), | ||||||
|  |             Err(LoadWithPersistError::InvalidChangeSet(LoadError::Mismatch( | ||||||
|  |                 LoadMismatch::Descriptor { .. } | ||||||
|  |             ))), | ||||||
|  |             "unexpected descriptors check result", | ||||||
|  |         ); | ||||||
|  | 
 | ||||||
|  |         Ok(()) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     run( | ||||||
|  |         "store.db", | ||||||
|  |         |path| Ok(bdk_file_store::Store::create_new(DB_MAGIC, path)?), | ||||||
|  |         |path| Ok(bdk_file_store::Store::open(DB_MAGIC, path)?), | ||||||
|  |     )?; | ||||||
|  |     run( | ||||||
|  |         "store.sqlite", | ||||||
|  |         |path| Ok(bdk_chain::sqlite::Connection::open(path)?), | ||||||
|  |         |path| Ok(bdk_chain::sqlite::Connection::open(path)?), | ||||||
|  |     )?; | ||||||
|  | 
 | ||||||
|  |     Ok(()) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #[test] | #[test] | ||||||
| fn test_error_external_and_internal_are_the_same() { | fn test_error_external_and_internal_are_the_same() { | ||||||
|     // identical descriptors should fail to create wallet
 |     // identical descriptors should fail to create wallet
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user