Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/cont_integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ jobs:
run: |
cargo update -p log --precise "0.4.18"
cargo update -p tempfile --precise "3.6.0"
cargo update -p minreq --precise "2.8.1"
cargo update -p rustls:0.21.6 --precise "0.21.1"
cargo update -p tokio:1.32.0 --precise "1.29.1"
cargo update -p flate2:1.0.27 --precise "1.0.26"
Expand Down
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@ members = [
"crates/file_store",
"crates/electrum",
"crates/esplora",
"crates/bitcoind_rpc",
"example-crates/example_cli",
"example-crates/example_electrum",
"example-crates/example_rpc",
"example-crates/wallet_electrum",
"example-crates/wallet_esplora_blocking",
"example-crates/wallet_esplora_async",
"example-crates/wallet_rpc",
"nursery/tmp_plan",
"nursery/coin_select"
]
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ To build with the MSRV you will need to pin dependencies as follows:
cargo update -p log --precise "0.4.18"
# tempfile 3.7.0 has MSRV 1.63.0+
cargo update -p tempfile --precise "3.6.0"
# minreq 2.9.0 prevents pinning rustls to 0.21.1
cargo update -p minreq --precise "2.8.1"
# rustls 0.21.2 has MSRV 1.60.0+
cargo update -p rustls:0.21.6 --precise "0.21.1"
# tokio 1.30 has MSRV 1.63.0+
Expand All @@ -79,7 +81,7 @@ cargo update -p flate2:1.0.27 --precise "1.0.26"
cargo update -p reqwest --precise "0.11.18"
# h2 0.3.21 has MSRV 1.63.0+
cargo update -p h2 --precise "0.3.20"
# rustls-webpki has MSRV 1.60.0+
# rustls-webpki 0.100.2 has MSRV 1.60.0+
cargo update -p rustls-webpki --precise "0.100.1"
```

Expand Down
113 changes: 110 additions & 3 deletions crates/bdk/src/wallet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ use alloc::{
pub use bdk_chain::keychain::Balance;
use bdk_chain::{
indexed_tx_graph,
keychain::{KeychainTxOutIndex, WalletChangeSet, WalletUpdate},
keychain::{self, KeychainTxOutIndex},
local_chain::{self, CannotConnectError, CheckPoint, CheckPointIter, LocalChain},
tx_graph::{CanonicalTx, TxGraph},
Append, BlockId, ChainPosition, ConfirmationTime, ConfirmationTimeAnchor, FullTxOut,
Anchor, Append, BlockId, ChainPosition, ConfirmationTime, ConfirmationTimeAnchor, FullTxOut,
IndexedTxGraph, Persist, PersistBackend,
};
use bitcoin::consensus::encode::serialize;
Expand Down Expand Up @@ -94,6 +94,90 @@ pub struct Wallet<D = ()> {
secp: SecpCtx,
}

/// A structure to update [`Wallet`].
///
/// It updates [`bdk_chain::keychain::KeychainTxOutIndex`], [`bdk_chain::TxGraph`] and [`local_chain::LocalChain`] atomically.
#[derive(Debug, Clone)]
pub struct WalletUpdate<K, A> {
/// Contains the last active derivation indices per keychain (`K`), which is used to update the
/// [`KeychainTxOutIndex`].
pub last_active_indices: BTreeMap<K, u32>,

/// Update for the [`TxGraph`].
pub graph: TxGraph<A>,

/// Update for the [`LocalChain`].
///
/// [`LocalChain`]: local_chain::LocalChain
pub chain: Option<local_chain::Update>,
}

impl<K, A> Default for WalletUpdate<K, A> {
fn default() -> Self {
Self {
last_active_indices: BTreeMap::new(),
graph: TxGraph::default(),
chain: None,
}
}
}

/// A structure that records the corresponding changes as result of applying an [`WalletUpdate`].
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct WalletChangeSet<K, A> {
/// Changes to the [`LocalChain`].
///
/// [`LocalChain`]: local_chain::LocalChain
pub chain: local_chain::ChangeSet,

/// ChangeSet to [`IndexedTxGraph`].
///
/// [`IndexedTxGraph`]: bdk_chain::indexed_tx_graph::IndexedTxGraph
#[serde(bound(
deserialize = "K: Ord + serde::Deserialize<'de>, A: Ord + serde::Deserialize<'de>",
serialize = "K: Ord + serde::Serialize, A: Ord + serde::Serialize",
))]
pub index_tx_graph: indexed_tx_graph::ChangeSet<A, keychain::ChangeSet<K>>,
}

impl<K, A> Default for WalletChangeSet<K, A> {
fn default() -> Self {
Self {
chain: Default::default(),
index_tx_graph: Default::default(),
}
}
}

impl<K: Ord, A: Anchor> Append for WalletChangeSet<K, A> {
fn append(&mut self, other: Self) {
Append::append(&mut self.chain, other.chain);
Append::append(&mut self.index_tx_graph, other.index_tx_graph);
}

fn is_empty(&self) -> bool {
self.chain.is_empty() && self.index_tx_graph.is_empty()
}
}

impl<K, A> From<local_chain::ChangeSet> for WalletChangeSet<K, A> {
fn from(chain: local_chain::ChangeSet) -> Self {
Self {
chain,
..Default::default()
}
}
}

impl<K, A> From<indexed_tx_graph::ChangeSet<A, keychain::ChangeSet<K>>> for WalletChangeSet<K, A> {
fn from(index_tx_graph: indexed_tx_graph::ChangeSet<A, keychain::ChangeSet<K>>) -> Self {
Self {
index_tx_graph,
..Default::default()
}
}
}

/// The update to a [`Wallet`] used in [`Wallet::apply_update`]. This is usually returned from blockchain data sources.
pub type Update = WalletUpdate<KeychainKind, ConfirmationTimeAnchor>;

Expand Down Expand Up @@ -1719,7 +1803,11 @@ impl<D> Wallet<D> {
where
D: PersistBackend<ChangeSet>,
{
let mut changeset = ChangeSet::from(self.chain.apply_update(update.chain)?);
let mut changeset = match update.chain {
Some(chain_update) => ChangeSet::from(self.chain.apply_update(chain_update)?),
None => ChangeSet::default(),
};

let (_, index_changeset) = self
.indexed_graph
.index
Expand Down Expand Up @@ -1758,11 +1846,25 @@ impl<D> Wallet<D> {
self.persist.staged()
}

/// Stages wallet changes in memory for later commit.
///
/// To commit changes to the persistence backend, call [`commit`].
///
/// [`commit`]: Self::commit
pub fn stage(&mut self, changeset: ChangeSet) where D: PersistBackend<ChangeSet> {
self.persist.stage(changeset);
}

/// Get a reference to the inner [`TxGraph`].
pub fn tx_graph(&self) -> &TxGraph<ConfirmationTimeAnchor> {
self.indexed_graph.graph()
}

/// Get a mutable reference to the inner [`IndexedTxGraph`].
pub fn mut_indexed_tx_graph(&mut self) -> &mut IndexedTxGraph<ConfirmationTimeAnchor, KeychainTxOutIndex<KeychainKind>> {
&mut self.indexed_graph
}

/// Get a reference to the inner [`KeychainTxOutIndex`].
pub fn spk_index(&self) -> &KeychainTxOutIndex<KeychainKind> {
&self.indexed_graph.index
Expand All @@ -1772,6 +1874,11 @@ impl<D> Wallet<D> {
pub fn local_chain(&self) -> &LocalChain {
&self.chain
}

/// Get a mutable reference to the inner [`LocalChain`].
pub fn mut_local_chain(&mut self) -> &mut LocalChain {
&mut self.chain
}
}

impl<D> AsRef<bdk_chain::tx_graph::TxGraph<ConfirmationTimeAnchor>> for Wallet<D> {
Expand Down
14 changes: 14 additions & 0 deletions crates/bitcoind_rpc/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "bdk_bitcoind_rpc"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
bdk_chain = { path = "../chain", version = "0.5.0", features = ["serde", "miniscript"] }
bitcoincore-rpc = { version = "0.17.0" }

[dev-dependencies]
bitcoind = { version = "0.32.0", features = ["25_0"] }
anyhow = { version = "1" }
Loading