network: Network,
) -> Result<Self, DescriptorError> {
Self::new(descriptor, change_descriptor, (), network).map_err(|e| match e {
+ NewError::NonEmptyDatabase => unreachable!("mock-database cannot have data"),
NewError::Descriptor(e) => e,
NewError::Write(_) => unreachable!("mock-write must always succeed"),
})
) -> Result<Self, crate::descriptor::DescriptorError> {
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::Write(_) => unreachable!("mock-write must always succeed"),
})
/// [`new_with_genesis_hash`]: Wallet::new_with_genesis_hash
#[derive(Debug)]
pub enum NewError<W> {
+ /// Database already has data.
+ NonEmptyDatabase,
/// There was problem with the passed-in descriptor(s).
Descriptor(crate::descriptor::DescriptorError),
/// We were unable to write the wallet's data to the persistence backend.
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
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::Write(e) => e.fmt(f),
}
pub fn new_with_genesis_hash<E: IntoWalletDescriptor>(
descriptor: E,
change_descriptor: Option<E>,
- db: D,
+ mut db: D,
network: Network,
genesis_hash: BlockHash,
) -> Result<Self, NewError<D::WriteError>>
where
D: PersistBackend<ChangeSet>,
{
+ if let Ok(changeset) = db.load_from_persistence() {
+ if changeset.is_some() {
+ return Err(NewError::NonEmptyDatabase);
+ }
+ }
let secp = Secp256k1::new();
let (chain, chain_changeset) = LocalChain::from_genesis_hash(genesis_hash);
let mut index = KeychainTxOutIndex::<KeychainKind>::default();
genesis_hash,
)
.map_err(|e| match e {
+ NewError::NonEmptyDatabase => {
+ unreachable!("database is already checked to have no data")
+ }
NewError::Descriptor(e) => NewOrLoadError::Descriptor(e),
NewError::Write(e) => NewOrLoadError::Write(e),
}),
use bdk::wallet::coin_selection::{self, LargestFirstCoinSelection};
use bdk::wallet::error::CreateTxError;
use bdk::wallet::tx_builder::AddForeignUtxoError;
-use bdk::wallet::AddressIndex::*;
use bdk::wallet::{AddressIndex, AddressInfo, Balance, Wallet};
+use bdk::wallet::{AddressIndex::*, NewError};
use bdk::{FeeRate, KeychainKind};
use bdk_chain::COINBASE_MATURITY;
use bdk_chain::{BlockId, ConfirmationTime};
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]