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