diff --git a/Cargo.toml b/Cargo.toml index 53ceb7cd47..87428029af 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ members = [ "crates/esplora", "crates/bitcoind_rpc", "crates/hwi", + "crates/persist", "crates/testenv", "example-crates/example_cli", "example-crates/example_electrum", diff --git a/README.md b/README.md index d322243085..907343c1dd 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ The project is split up into several crates in the `/crates` directory: - [`bdk`](./crates/bdk): Contains the central high level `Wallet` type that is built from the low-level mechanisms provided by the other components - [`chain`](./crates/chain): Tools for storing and indexing chain data +- [`persist`](./crates/persist): Types that define data persistence of a BDK wallet - [`file_store`](./crates/file_store): A (experimental) persistence backend for storing chain data in a single file. - [`esplora`](./crates/esplora): Extends the [`esplora-client`] crate with methods to fetch chain data from an esplora HTTP server in the form that [`bdk_chain`] and `Wallet` can consume. - [`electrum`](./crates/electrum): Extends the [`electrum-client`] crate with methods to fetch chain data from an electrum server in the form that [`bdk_chain`] and `Wallet` can consume. @@ -61,6 +62,7 @@ Fully working examples of how to use these components are in `/example-crates`: [`electrum-client`]: https://docs.rs/electrum-client/ [`bdk_chain`]: https://docs.rs/bdk-chain/ + ## Minimum Supported Rust Version (MSRV) This library should compile with any combination of features with Rust 1.63.0. diff --git a/crates/bdk/Cargo.toml b/crates/bdk/Cargo.toml index 425199e101..8c21a94d42 100644 --- a/crates/bdk/Cargo.toml +++ b/crates/bdk/Cargo.toml @@ -20,6 +20,8 @@ bitcoin = { version = "0.31.0", features = ["serde", "base64", "rand-std"], defa serde = { version = "^1.0", features = ["derive"] } serde_json = { version = "^1.0" } bdk_chain = { path = "../chain", version = "0.12.0", features = ["miniscript", "serde"], default-features = false } +bdk_persist = { path = "../persist", version = "0.1.0" } + # Optional dependencies bip39 = { version = "2.0", optional = true } diff --git a/crates/bdk/README.md b/crates/bdk/README.md index a3d53f2950..4722c5845b 100644 --- a/crates/bdk/README.md +++ b/crates/bdk/README.md @@ -219,7 +219,7 @@ license, shall be dual licensed as above, without any additional terms or conditions. [`Wallet`]: https://docs.rs/bdk/1.0.0-alpha.7/bdk/wallet/struct.Wallet.html -[`PersistBackend`]: https://docs.rs/bdk_chain/latest/bdk_chain/trait.PersistBackend.html +[`PersistBackend`]: https://docs.rs/bdk_persist/latest/bdk_persist/trait.PersistBackend.html [`bdk_chain`]: https://docs.rs/bdk_chain/latest [`bdk_file_store`]: https://docs.rs/bdk_file_store/latest [`bdk_electrum`]: https://docs.rs/bdk_electrum/latest diff --git a/crates/bdk/src/wallet/coin_selection.rs b/crates/bdk/src/wallet/coin_selection.rs index 49cb56c0cb..f1897677bf 100644 --- a/crates/bdk/src/wallet/coin_selection.rs +++ b/crates/bdk/src/wallet/coin_selection.rs @@ -28,7 +28,7 @@ //! # use bitcoin::*; //! # use bdk::wallet::{self, ChangeSet, coin_selection::*, coin_selection}; //! # use bdk::wallet::error::CreateTxError; -//! # use bdk_chain::PersistBackend; +//! # use bdk_persist::PersistBackend; //! # use bdk::*; //! # use bdk::wallet::coin_selection::decide_change; //! # use anyhow::Error; diff --git a/crates/bdk/src/wallet/mod.rs b/crates/bdk/src/wallet/mod.rs index 1e24dd50e4..1fe37d5508 100644 --- a/crates/bdk/src/wallet/mod.rs +++ b/crates/bdk/src/wallet/mod.rs @@ -28,8 +28,9 @@ use bdk_chain::{ }, tx_graph::{CanonicalTx, TxGraph}, Append, BlockId, ChainPosition, ConfirmationTime, ConfirmationTimeHeightAnchor, FullTxOut, - IndexedTxGraph, Persist, PersistBackend, + IndexedTxGraph, }; +use bdk_persist::{Persist, PersistBackend}; use bitcoin::constants::genesis_block; use bitcoin::secp256k1::{All, Secp256k1}; use bitcoin::sighash::{EcdsaSighashType, TapSighashType}; @@ -1167,7 +1168,7 @@ impl Wallet { /// # use bdk::*; /// # use bdk::wallet::ChangeSet; /// # use bdk::wallet::error::CreateTxError; - /// # use bdk_chain::PersistBackend; + /// # use bdk_persist::PersistBackend; /// # use anyhow::Error; /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)"; /// # let mut wallet = doctest_wallet!(); @@ -1549,7 +1550,7 @@ impl Wallet { /// # use bdk::*; /// # use bdk::wallet::ChangeSet; /// # use bdk::wallet::error::CreateTxError; - /// # use bdk_chain::PersistBackend; + /// # use bdk_persist::PersistBackend; /// # use anyhow::Error; /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)"; /// # let mut wallet = doctest_wallet!(); @@ -1724,7 +1725,7 @@ impl Wallet { /// # use bdk::*; /// # use bdk::wallet::ChangeSet; /// # use bdk::wallet::error::CreateTxError; - /// # use bdk_chain::PersistBackend; + /// # use bdk_persist::PersistBackend; /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)"; /// # let mut wallet = doctest_wallet!(); /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap().assume_checked(); diff --git a/crates/bdk/src/wallet/tx_builder.rs b/crates/bdk/src/wallet/tx_builder.rs index e7df86678d..355d80d3bc 100644 --- a/crates/bdk/src/wallet/tx_builder.rs +++ b/crates/bdk/src/wallet/tx_builder.rs @@ -20,7 +20,7 @@ //! # use bdk::wallet::ChangeSet; //! # use bdk::wallet::error::CreateTxError; //! # use bdk::wallet::tx_builder::CreateTx; -//! # use bdk_chain::PersistBackend; +//! # use bdk_persist::PersistBackend; //! # use anyhow::Error; //! # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap().assume_checked(); //! # let mut wallet = doctest_wallet!(); @@ -84,7 +84,7 @@ impl TxBuilderContext for BumpFee {} /// # use core::str::FromStr; /// # use bdk::wallet::ChangeSet; /// # use bdk::wallet::error::CreateTxError; -/// # use bdk_chain::PersistBackend; +/// # use bdk_persist::PersistBackend; /// # use anyhow::Error; /// # let mut wallet = doctest_wallet!(); /// # let addr1 = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap().assume_checked(); @@ -758,7 +758,7 @@ impl<'a, Cs: CoinSelectionAlgorithm> TxBuilder<'a, Cs, CreateTx> { /// # use bdk::wallet::ChangeSet; /// # use bdk::wallet::error::CreateTxError; /// # use bdk::wallet::tx_builder::CreateTx; - /// # use bdk_chain::PersistBackend; + /// # use bdk_persist::PersistBackend; /// # use anyhow::Error; /// # let to_address = /// Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt") diff --git a/crates/chain/Cargo.toml b/crates/chain/Cargo.toml index 56cadd85a1..fda5924d2f 100644 --- a/crates/chain/Cargo.toml +++ b/crates/chain/Cargo.toml @@ -14,7 +14,6 @@ readme = "README.md" [dependencies] # For no-std, remember to enable the bitcoin/no-std feature -anyhow = { version = "1", default-features = false } bitcoin = { version = "0.31.0", default-features = false } serde_crate = { package = "serde", version = "1", optional = true, features = ["derive", "rc"] } diff --git a/crates/chain/src/lib.rs b/crates/chain/src/lib.rs index 2065669714..61c0b6d7ac 100644 --- a/crates/chain/src/lib.rs +++ b/crates/chain/src/lib.rs @@ -35,8 +35,6 @@ pub use tx_data_traits::*; pub use tx_graph::TxGraph; mod chain_oracle; pub use chain_oracle::*; -mod persist; -pub use persist::*; #[doc(hidden)] pub mod example_utils; diff --git a/crates/file_store/Cargo.toml b/crates/file_store/Cargo.toml index 0d382b4bf7..9994190589 100644 --- a/crates/file_store/Cargo.toml +++ b/crates/file_store/Cargo.toml @@ -13,6 +13,8 @@ readme = "README.md" [dependencies] anyhow = { version = "1", default-features = false } bdk_chain = { path = "../chain", version = "0.12.0", features = [ "serde", "miniscript" ] } +bdk_persist = { path = "../persist", version = "0.1.0"} + bincode = { version = "1" } serde = { version = "1", features = ["derive"] } diff --git a/crates/file_store/README.md b/crates/file_store/README.md index 4a334fcbfa..54e41e007f 100644 --- a/crates/file_store/README.md +++ b/crates/file_store/README.md @@ -1,10 +1,10 @@ # BDK File Store This is a simple append-only flat file implementation of -[`Persist`](`bdk_chain::Persist`). +[`PersistBackend`](bdk_persist::PersistBackend). -The main structure is [`Store`](`crate::Store`), which can be used with [`bdk`]'s +The main structure is [`Store`](crate::Store), which can be used with [`bdk`]'s `Wallet` to persist wallet data into a flat file. [`bdk`]: https://docs.rs/bdk/latest -[`bdk_chain`]: https://docs.rs/bdk_chain/latest +[`bdk_persist`]: https://docs.rs/bdk_persist/latest diff --git a/crates/file_store/src/store.rs b/crates/file_store/src/store.rs index 16d8f7b72a..6cea927657 100644 --- a/crates/file_store/src/store.rs +++ b/crates/file_store/src/store.rs @@ -1,6 +1,7 @@ use crate::{bincode_options, EntryIter, FileError, IterError}; use anyhow::anyhow; -use bdk_chain::{Append, PersistBackend}; +use bdk_chain::Append; +use bdk_persist::PersistBackend; use bincode::Options; use std::{ fmt::{self, Debug}, @@ -11,8 +12,6 @@ use std::{ }; /// Persists an append-only list of changesets (`C`) to a single file. -/// -/// The changesets are the results of altering a tracker implementation (`T`). #[derive(Debug)] pub struct Store where @@ -152,7 +151,7 @@ where /// /// You should usually check the error. In many applications, it may make sense to do a full /// wallet scan with a stop-gap after getting an error, since it is likely that one of the - /// changesets it was unable to read changed the derivation indices of the tracker. + /// changesets was unable to read changes of the derivation indices of a keychain. /// /// **WARNING**: This method changes the write position of the underlying file. The next /// changeset will be written over the erroring entry (or the end of the file if none existed). @@ -240,9 +239,6 @@ mod test { type TestChangeSet = BTreeSet; - #[derive(Debug)] - struct TestTracker; - /// Check behavior of [`Store::create_new`] and [`Store::open`]. #[test] fn construct_store() { diff --git a/crates/persist/Cargo.toml b/crates/persist/Cargo.toml new file mode 100644 index 0000000000..257ab54504 --- /dev/null +++ b/crates/persist/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "bdk_persist" +homepage = "https://bitcoindevkit.org" +version = "0.1.0" +repository = "https://github.com/bitcoindevkit/bdk" +documentation = "https://docs.rs/bdk_persist" +description = "Types that define data persistence of a BDK wallet" +keywords = ["bitcoin", "wallet", "persistence", "database"] +readme = "README.md" +license = "MIT OR Apache-2.0" +authors = ["Bitcoin Dev Kit Developers"] +edition = "2021" +rust-version = "1.63" + +[dependencies] +anyhow = { version = "1", default-features = false } +bdk_chain = { path = "../chain", version = "0.12.0", default-features = false } + + diff --git a/crates/persist/README.md b/crates/persist/README.md new file mode 100644 index 0000000000..1ed6ec8d27 --- /dev/null +++ b/crates/persist/README.md @@ -0,0 +1,3 @@ +# BDK Persist + +This crate is home to the [`PersistBackend`](crate::PersistBackend) trait which defines the behavior of a database to perform the task of persisting changes made to BDK data structures. The [`Persist`](crate::Persist) type provides a convenient wrapper around a `PersistBackend` that allows staging changes before committing them. \ No newline at end of file diff --git a/crates/persist/src/lib.rs b/crates/persist/src/lib.rs new file mode 100644 index 0000000000..e055f2a44e --- /dev/null +++ b/crates/persist/src/lib.rs @@ -0,0 +1,5 @@ +#![doc = include_str!("../README.md")] +#![no_std] +#![warn(missing_docs)] +mod persist; +pub use persist::*; diff --git a/crates/chain/src/persist.rs b/crates/persist/src/persist.rs similarity index 98% rename from crates/chain/src/persist.rs rename to crates/persist/src/persist.rs index 64efa55b4d..5d9df3bf6d 100644 --- a/crates/chain/src/persist.rs +++ b/crates/persist/src/persist.rs @@ -1,5 +1,6 @@ -use crate::Append; +extern crate alloc; use alloc::boxed::Box; +use bdk_chain::Append; use core::fmt; /// `Persist` wraps a [`PersistBackend`] to create a convenient staging area for changes (`C`) diff --git a/example-crates/example_cli/Cargo.toml b/example-crates/example_cli/Cargo.toml index c85d2e9963..42a0b51b09 100644 --- a/example-crates/example_cli/Cargo.toml +++ b/example-crates/example_cli/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" [dependencies] bdk_chain = { path = "../../crates/chain", features = ["serde", "miniscript"]} +bdk_persist = { path = "../../crates/persist" } bdk_file_store = { path = "../../crates/file_store" } bdk_tmp_plan = { path = "../../nursery/tmp_plan" } bdk_coin_select = { path = "../../nursery/coin_select" } diff --git a/example-crates/example_cli/src/lib.rs b/example-crates/example_cli/src/lib.rs index e7c4efece2..5671a6b824 100644 --- a/example-crates/example_cli/src/lib.rs +++ b/example-crates/example_cli/src/lib.rs @@ -19,9 +19,10 @@ use bdk_chain::{ descriptor::{DescriptorSecretKey, KeyMap}, Descriptor, DescriptorPublicKey, }, - Anchor, Append, ChainOracle, DescriptorExt, FullTxOut, Persist, PersistBackend, + Anchor, Append, ChainOracle, DescriptorExt, FullTxOut, }; pub use bdk_file_store; +use bdk_persist::{Persist, PersistBackend}; pub use clap; use clap::{Parser, Subcommand};