feat!: Rework sqlite, changesets, persistence and wallet-construction
Rework sqlite: Instead of only supported one schema (defined in `bdk_sqlite`), we have a schema per changeset type for more flexiblity. * rm `bdk_sqlite` crate (as we don't need `bdk_sqlite::Store` anymore). * add `sqlite` feature on `bdk_chain` which adds methods on each changeset type for initializing tables, loading the changeset and writing. Rework changesets: Some callers may want to use `KeychainTxOutIndex` where `K` may change per descriptor on every run. So we only want to persist the last revealed indices by `DescriptorId` (which uniquely-ish identifies the descriptor). * rm `keychain_added` field from `keychain_txout`'s changeset. * Add `keychain_added` to `CombinedChangeSet` (which is renamed to `WalletChangeSet`). Rework persistence: add back some safety and convenience when persisting our types. Working with changeset directly (as we were doing before) can be cumbersome. * Intoduce `struct Persisted<T>` which wraps a type `T` which stores staged changes to it. This adds safety when creating and or loading `T` from db. * `struct Persisted<T>` methods, `create`, `load` and `persist`, are avaliable if `trait PersistWith<Db>` is implemented for `T`. `Db` represents the database connection and `PersistWith` should be implemented per database-type. * For async, we have `trait PersistedAsyncWith<Db>`. * `Wallet` has impls of `PersistedWith<rusqlite::Connection>`, `PersistedWith<rusqlite::Transaction>` and `PersistedWith<bdk_file_store::Store>` by default. Rework wallet-construction: Before, we had multiple methods for loading and creating with different input-counts so it would be unwieldly to add more parameters in the future. This also makes it difficult to impl `PersistWith` (which has a single method for `load` that takes in `PersistWith::LoadParams` and a single method for `create` that takes in `PersistWith::CreateParams`). * Introduce a builder pattern when constructing a `Wallet`. For loading from persistence or `ChangeSet`, we have `LoadParams`. For creating a new wallet, we have `CreateParams`.
This commit is contained in:
@@ -6,7 +6,7 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
bdk_wallet = { path = "../../crates/wallet" }
|
||||
bdk_wallet = { path = "../../crates/wallet", features = ["file_store"] }
|
||||
bdk_file_store = { path = "../../crates/file_store" }
|
||||
bdk_bitcoind_rpc = { path = "../../crates/bitcoind_rpc" }
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ use bdk_bitcoind_rpc::{
|
||||
use bdk_file_store::Store;
|
||||
use bdk_wallet::{
|
||||
bitcoin::{Block, Network, Transaction},
|
||||
wallet::Wallet,
|
||||
wallet::{CreateParams, LoadParams},
|
||||
};
|
||||
use clap::{self, Parser};
|
||||
use std::{path::PathBuf, sync::mpsc::sync_channel, thread::spawn, time::Instant};
|
||||
@@ -90,14 +90,14 @@ fn main() -> anyhow::Result<()> {
|
||||
DB_MAGIC.as_bytes(),
|
||||
args.db_path,
|
||||
)?;
|
||||
let changeset = db.aggregate_changesets()?;
|
||||
|
||||
let mut wallet = Wallet::new_or_load(
|
||||
&args.descriptor,
|
||||
&args.change_descriptor,
|
||||
changeset,
|
||||
args.network,
|
||||
)?;
|
||||
let load_params =
|
||||
LoadParams::with_descriptors(&args.descriptor, &args.change_descriptor, args.network)?;
|
||||
let create_params = CreateParams::new(&args.descriptor, &args.change_descriptor, args.network)?;
|
||||
let mut wallet = match load_params.load_wallet(&mut db)? {
|
||||
Some(wallet) => wallet,
|
||||
None => create_params.create_wallet(&mut db)?,
|
||||
};
|
||||
println!(
|
||||
"Loaded wallet in {}s",
|
||||
start_load_wallet.elapsed().as_secs_f32()
|
||||
@@ -146,9 +146,7 @@ fn main() -> anyhow::Result<()> {
|
||||
let connected_to = block_emission.connected_to();
|
||||
let start_apply_block = Instant::now();
|
||||
wallet.apply_block_connected_to(&block_emission.block, height, connected_to)?;
|
||||
if let Some(changeset) = wallet.take_staged() {
|
||||
db.append_changeset(&changeset)?;
|
||||
}
|
||||
wallet.persist(&mut db)?;
|
||||
let elapsed = start_apply_block.elapsed().as_secs_f32();
|
||||
println!(
|
||||
"Applied block {} at height {} in {}s",
|
||||
@@ -158,9 +156,7 @@ fn main() -> anyhow::Result<()> {
|
||||
Emission::Mempool(mempool_emission) => {
|
||||
let start_apply_mempool = Instant::now();
|
||||
wallet.apply_unconfirmed_txs(mempool_emission.iter().map(|(tx, time)| (tx, *time)));
|
||||
if let Some(changeset) = wallet.take_staged() {
|
||||
db.append_changeset(&changeset)?;
|
||||
}
|
||||
wallet.persist(&mut db)?;
|
||||
println!(
|
||||
"Applied unconfirmed transactions in {}s",
|
||||
start_apply_mempool.elapsed().as_secs_f32()
|
||||
|
||||
Reference in New Issue
Block a user