feat(wallet)!: add NonEmptyDatabase
variant to NewError
`NewError` is the error type when constructing a wallet with `Wallet::new`. We want this to return an error when the database already contains data (in which case, the caller should use `load` or `new_or_load`).
This commit is contained in:
parent
9cc03324f4
commit
a1d34afa24
@ -237,6 +237,7 @@ impl Wallet {
|
|||||||
network: Network,
|
network: Network,
|
||||||
) -> Result<Self, DescriptorError> {
|
) -> Result<Self, DescriptorError> {
|
||||||
Self::new(descriptor, change_descriptor, (), network).map_err(|e| match e {
|
Self::new(descriptor, change_descriptor, (), network).map_err(|e| match e {
|
||||||
|
NewError::NonEmptyDatabase => unreachable!("mock-database cannot have data"),
|
||||||
NewError::Descriptor(e) => e,
|
NewError::Descriptor(e) => e,
|
||||||
NewError::Write(_) => unreachable!("mock-write must always succeed"),
|
NewError::Write(_) => unreachable!("mock-write must always succeed"),
|
||||||
})
|
})
|
||||||
@ -251,6 +252,7 @@ impl Wallet {
|
|||||||
) -> Result<Self, crate::descriptor::DescriptorError> {
|
) -> Result<Self, crate::descriptor::DescriptorError> {
|
||||||
Self::new_with_genesis_hash(descriptor, change_descriptor, (), network, genesis_hash)
|
Self::new_with_genesis_hash(descriptor, change_descriptor, (), network, genesis_hash)
|
||||||
.map_err(|e| match e {
|
.map_err(|e| match e {
|
||||||
|
NewError::NonEmptyDatabase => unreachable!("mock-database cannot have data"),
|
||||||
NewError::Descriptor(e) => e,
|
NewError::Descriptor(e) => e,
|
||||||
NewError::Write(_) => unreachable!("mock-write must always succeed"),
|
NewError::Write(_) => unreachable!("mock-write must always succeed"),
|
||||||
})
|
})
|
||||||
@ -288,6 +290,8 @@ where
|
|||||||
/// [`new_with_genesis_hash`]: Wallet::new_with_genesis_hash
|
/// [`new_with_genesis_hash`]: Wallet::new_with_genesis_hash
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum NewError<W> {
|
pub enum NewError<W> {
|
||||||
|
/// Database already has data.
|
||||||
|
NonEmptyDatabase,
|
||||||
/// There was problem with the passed-in descriptor(s).
|
/// There was problem with the passed-in descriptor(s).
|
||||||
Descriptor(crate::descriptor::DescriptorError),
|
Descriptor(crate::descriptor::DescriptorError),
|
||||||
/// We were unable to write the wallet's data to the persistence backend.
|
/// We were unable to write the wallet's data to the persistence backend.
|
||||||
@ -300,6 +304,10 @@ where
|
|||||||
{
|
{
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
|
NewError::NonEmptyDatabase => write!(
|
||||||
|
f,
|
||||||
|
"database already has data - use `load` or `new_or_load` methods instead"
|
||||||
|
),
|
||||||
NewError::Descriptor(e) => e.fmt(f),
|
NewError::Descriptor(e) => e.fmt(f),
|
||||||
NewError::Write(e) => e.fmt(f),
|
NewError::Write(e) => e.fmt(f),
|
||||||
}
|
}
|
||||||
@ -446,13 +454,18 @@ impl<D> Wallet<D> {
|
|||||||
pub fn new_with_genesis_hash<E: IntoWalletDescriptor>(
|
pub fn new_with_genesis_hash<E: IntoWalletDescriptor>(
|
||||||
descriptor: E,
|
descriptor: E,
|
||||||
change_descriptor: Option<E>,
|
change_descriptor: Option<E>,
|
||||||
db: D,
|
mut db: D,
|
||||||
network: Network,
|
network: Network,
|
||||||
genesis_hash: BlockHash,
|
genesis_hash: BlockHash,
|
||||||
) -> Result<Self, NewError<D::WriteError>>
|
) -> Result<Self, NewError<D::WriteError>>
|
||||||
where
|
where
|
||||||
D: PersistBackend<ChangeSet>,
|
D: PersistBackend<ChangeSet>,
|
||||||
{
|
{
|
||||||
|
if let Ok(changeset) = db.load_from_persistence() {
|
||||||
|
if changeset.is_some() {
|
||||||
|
return Err(NewError::NonEmptyDatabase);
|
||||||
|
}
|
||||||
|
}
|
||||||
let secp = Secp256k1::new();
|
let secp = Secp256k1::new();
|
||||||
let (chain, chain_changeset) = LocalChain::from_genesis_hash(genesis_hash);
|
let (chain, chain_changeset) = LocalChain::from_genesis_hash(genesis_hash);
|
||||||
let mut index = KeychainTxOutIndex::<KeychainKind>::default();
|
let mut index = KeychainTxOutIndex::<KeychainKind>::default();
|
||||||
@ -615,6 +628,9 @@ impl<D> Wallet<D> {
|
|||||||
genesis_hash,
|
genesis_hash,
|
||||||
)
|
)
|
||||||
.map_err(|e| match e {
|
.map_err(|e| match e {
|
||||||
|
NewError::NonEmptyDatabase => {
|
||||||
|
unreachable!("database is already checked to have no data")
|
||||||
|
}
|
||||||
NewError::Descriptor(e) => NewOrLoadError::Descriptor(e),
|
NewError::Descriptor(e) => NewOrLoadError::Descriptor(e),
|
||||||
NewError::Write(e) => NewOrLoadError::Write(e),
|
NewError::Write(e) => NewOrLoadError::Write(e),
|
||||||
}),
|
}),
|
||||||
|
@ -7,8 +7,8 @@ use bdk::signer::{SignOptions, SignerError};
|
|||||||
use bdk::wallet::coin_selection::{self, LargestFirstCoinSelection};
|
use bdk::wallet::coin_selection::{self, LargestFirstCoinSelection};
|
||||||
use bdk::wallet::error::CreateTxError;
|
use bdk::wallet::error::CreateTxError;
|
||||||
use bdk::wallet::tx_builder::AddForeignUtxoError;
|
use bdk::wallet::tx_builder::AddForeignUtxoError;
|
||||||
use bdk::wallet::AddressIndex::*;
|
|
||||||
use bdk::wallet::{AddressIndex, AddressInfo, Balance, Wallet};
|
use bdk::wallet::{AddressIndex, AddressInfo, Balance, Wallet};
|
||||||
|
use bdk::wallet::{AddressIndex::*, NewError};
|
||||||
use bdk::{FeeRate, KeychainKind};
|
use bdk::{FeeRate, KeychainKind};
|
||||||
use bdk_chain::COINBASE_MATURITY;
|
use bdk_chain::COINBASE_MATURITY;
|
||||||
use bdk_chain::{BlockId, ConfirmationTime};
|
use bdk_chain::{BlockId, ConfirmationTime};
|
||||||
@ -92,6 +92,13 @@ fn load_recovers_wallet() {
|
|||||||
wallet_spk_index.last_revealed_indices()
|
wallet_spk_index.last_revealed_indices()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// `new` can only be called on empty db
|
||||||
|
{
|
||||||
|
let db = bdk_file_store::Store::open(DB_MAGIC, &file_path).expect("must recover db");
|
||||||
|
let result = Wallet::new(get_test_tr_single_sig_xprv(), None, db, Network::Testnet);
|
||||||
|
assert!(matches!(result, Err(NewError::NonEmptyDatabase)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user