Skip to content

Commit d43ae02

Browse files
refactor: improve docs, cleanup unnecessary types and improve code
1 parent 4104206 commit d43ae02

File tree

11 files changed

+175
-169
lines changed

11 files changed

+175
-169
lines changed

crates/bdk/src/wallet/mod.rs

Lines changed: 29 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use bdk_chain::{
2525
keychain::{self, KeychainTxOutIndex},
2626
local_chain::{self, CannotConnectError, CheckPoint, CheckPointIter, LocalChain},
2727
tx_graph::{CanonicalTx, TxGraph},
28-
Anchor, Append, BlockId, ChainPosition, ConfirmationTime, ConfirmationTimeAnchor, FullTxOut,
28+
Append, BlockId, ChainPosition, ConfirmationTime, ConfirmationTimeAnchor, FullTxOut,
2929
IndexedTxGraph, Persist, PersistBackend,
3030
};
3131
use bitcoin::consensus::encode::serialize;
@@ -95,73 +95,51 @@ pub struct Wallet<D = ()> {
9595
secp: SecpCtx,
9696
}
9797

98-
/// A structure to update [`Wallet`].
98+
/// An update to [`Wallet`].
9999
///
100100
/// It updates [`bdk_chain::keychain::KeychainTxOutIndex`], [`bdk_chain::TxGraph`] and [`local_chain::LocalChain`] atomically.
101-
#[derive(Debug, Clone)]
102-
pub struct WalletUpdate<K, A> {
101+
#[derive(Debug, Clone, Default)]
102+
pub struct Update {
103103
/// Contains the last active derivation indices per keychain (`K`), which is used to update the
104104
/// [`KeychainTxOutIndex`].
105-
pub last_active_indices: BTreeMap<K, u32>,
105+
pub last_active_indices: BTreeMap<KeychainKind, u32>,
106106

107-
/// Update for the [`TxGraph`].
108-
pub graph: TxGraph<A>,
107+
/// Update for the wallet's internal [`TxGraph`].
108+
pub graph: TxGraph<ConfirmationTimeAnchor>,
109109

110-
/// Update for the [`LocalChain`].
110+
/// Update for the wallet's internal [`LocalChain`].
111111
///
112112
/// [`LocalChain`]: local_chain::LocalChain
113113
pub chain: Option<local_chain::Update>,
114114
}
115115

116-
impl<K, A> Default for WalletUpdate<K, A> {
117-
fn default() -> Self {
118-
Self {
119-
last_active_indices: BTreeMap::new(),
120-
graph: TxGraph::default(),
121-
chain: None,
122-
}
123-
}
124-
}
125-
126-
/// A structure that records the corresponding changes as result of applying an [`WalletUpdate`].
127-
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
128-
pub struct WalletChangeSet<K, A> {
116+
/// The changes made to a wallet by applying an [`Update`].
117+
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, Default)]
118+
pub struct ChangeSet {
129119
/// Changes to the [`LocalChain`].
130120
///
131121
/// [`LocalChain`]: local_chain::LocalChain
132122
pub chain: local_chain::ChangeSet,
133123

134-
/// ChangeSet to [`IndexedTxGraph`].
124+
/// Changes to [`IndexedTxGraph`].
135125
///
136126
/// [`IndexedTxGraph`]: bdk_chain::indexed_tx_graph::IndexedTxGraph
137-
#[serde(bound(
138-
deserialize = "K: Ord + serde::Deserialize<'de>, A: Ord + serde::Deserialize<'de>",
139-
serialize = "K: Ord + serde::Serialize, A: Ord + serde::Serialize",
140-
))]
141-
pub index_tx_graph: indexed_tx_graph::ChangeSet<A, keychain::ChangeSet<K>>,
127+
pub indexed_tx_graph:
128+
indexed_tx_graph::ChangeSet<ConfirmationTimeAnchor, keychain::ChangeSet<KeychainKind>>,
142129
}
143130

144-
impl<K, A> Default for WalletChangeSet<K, A> {
145-
fn default() -> Self {
146-
Self {
147-
chain: Default::default(),
148-
index_tx_graph: Default::default(),
149-
}
150-
}
151-
}
152-
153-
impl<K: Ord, A: Anchor> Append for WalletChangeSet<K, A> {
131+
impl Append for ChangeSet {
154132
fn append(&mut self, other: Self) {
155133
Append::append(&mut self.chain, other.chain);
156-
Append::append(&mut self.index_tx_graph, other.index_tx_graph);
134+
Append::append(&mut self.indexed_tx_graph, other.indexed_tx_graph);
157135
}
158136

159137
fn is_empty(&self) -> bool {
160-
self.chain.is_empty() && self.index_tx_graph.is_empty()
138+
self.chain.is_empty() && self.indexed_tx_graph.is_empty()
161139
}
162140
}
163141

164-
impl<K, A> From<local_chain::ChangeSet> for WalletChangeSet<K, A> {
142+
impl From<local_chain::ChangeSet> for ChangeSet {
165143
fn from(chain: local_chain::ChangeSet) -> Self {
166144
Self {
167145
chain,
@@ -170,21 +148,22 @@ impl<K, A> From<local_chain::ChangeSet> for WalletChangeSet<K, A> {
170148
}
171149
}
172150

173-
impl<K, A> From<indexed_tx_graph::ChangeSet<A, keychain::ChangeSet<K>>> for WalletChangeSet<K, A> {
174-
fn from(index_tx_graph: indexed_tx_graph::ChangeSet<A, keychain::ChangeSet<K>>) -> Self {
151+
impl From<indexed_tx_graph::ChangeSet<ConfirmationTimeAnchor, keychain::ChangeSet<KeychainKind>>>
152+
for ChangeSet
153+
{
154+
fn from(
155+
indexed_tx_graph: indexed_tx_graph::ChangeSet<
156+
ConfirmationTimeAnchor,
157+
keychain::ChangeSet<KeychainKind>,
158+
>,
159+
) -> Self {
175160
Self {
176-
index_tx_graph,
161+
indexed_tx_graph,
177162
..Default::default()
178163
}
179164
}
180165
}
181166

182-
/// The update to a [`Wallet`] used in [`Wallet::apply_update`]. This is usually returned from blockchain data sources.
183-
pub type Update = WalletUpdate<KeychainKind, ConfirmationTimeAnchor>;
184-
185-
/// The changeset produced internally by [`Wallet`] when mutated.
186-
pub type ChangeSet = WalletChangeSet<KeychainKind, ConfirmationTimeAnchor>;
187-
188167
/// The address index selection strategy to use to derived an address from the wallet's external
189168
/// descriptor. See [`Wallet::get_address`]. If you're unsure which one to use use `WalletIndex::New`.
190169
#[derive(Debug)]
@@ -332,7 +311,7 @@ impl<D> Wallet<D> {
332311

333312
let changeset = db.load_from_persistence().map_err(NewError::Persist)?;
334313
chain.apply_changeset(&changeset.chain);
335-
indexed_graph.apply_changeset(changeset.index_tx_graph);
314+
indexed_graph.apply_changeset(changeset.indexed_tx_graph);
336315

337316
let persist = Persist::new(db);
338317

crates/chain/src/indexed_tx_graph.rs

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use alloc::vec::Vec;
66
use bitcoin::{OutPoint, Transaction, TxOut};
77

88
use crate::{
9-
keychain,
9+
keychain, local_chain,
1010
tx_graph::{self, TxGraph},
1111
Anchor, Append,
1212
};
@@ -225,7 +225,16 @@ impl<A, K> From<keychain::ChangeSet<K>> for ChangeSet<A, keychain::ChangeSet<K>>
225225
}
226226
}
227227

228-
/// Represents a structure that can index transaction data.
228+
impl<A, IA> From<ChangeSet<A, IA>> for (local_chain::ChangeSet, ChangeSet<A, IA>) {
229+
fn from(indexed_changeset: ChangeSet<A, IA>) -> Self {
230+
(local_chain::ChangeSet::default(), indexed_changeset)
231+
}
232+
}
233+
234+
/// Utilities for indexing transaction data.
235+
///
236+
/// Types which implement this trait can be used to construct an [`IndexedTxGraph`].
237+
/// This trait's methods should rarely be called directly.
229238
pub trait Indexer {
230239
/// The resultant "changeset" when new transaction data is indexed.
231240
type ChangeSet;
@@ -234,17 +243,6 @@ pub trait Indexer {
234243
fn index_txout(&mut self, outpoint: OutPoint, txout: &TxOut) -> Self::ChangeSet;
235244

236245
/// Scans a transaction for relevant outpoints, which are stored and indexed internally.
237-
///
238-
/// If the matched script pubkey is part of the lookahead, the last stored index is updated for
239-
/// the script pubkey's keychain and the [`ChangeSet`] returned will reflect the
240-
/// change.
241-
///
242-
/// Typically, this method is used in two situations:
243-
///
244-
/// 1. After loading transaction data from the disk, you may scan over all the txouts to restore all
245-
/// your txouts.
246-
/// 2. When getting new data from the chain, you usually scan it before incorporating it into
247-
/// your chain state.
248246
fn index_tx(&mut self, tx: &Transaction) -> Self::ChangeSet;
249247

250248
/// Apply changeset to itself.

crates/chain/src/keychain/txout_index.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,10 @@ impl<K: Clone + Ord + Debug> Indexer for KeychainTxOutIndex<K> {
9191
type ChangeSet = super::ChangeSet<K>;
9292

9393
fn index_txout(&mut self, outpoint: OutPoint, txout: &TxOut) -> Self::ChangeSet {
94-
let mut changeset = super::ChangeSet::<K>::default();
95-
for (keychain, index) in self.inner.index_txout(outpoint, txout) {
96-
changeset.append(self.reveal_to_target(&keychain, index).1);
94+
match self.inner.scan_txout(outpoint, txout).cloned() {
95+
Some((keychain, index)) => self.reveal_to_target(&keychain, index).1,
96+
None => super::ChangeSet::default(),
9797
}
98-
changeset
9998
}
10099

101100
fn index_tx(&mut self, tx: &bitcoin::Transaction) -> Self::ChangeSet {
@@ -175,8 +174,10 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
175174

176175
/// Set the lookahead count for `keychain`.
177176
///
178-
/// The lookahead is the number of scripts to cache ahead of the last stored script index. This
179-
/// is useful during a scan via [`Indexer::index_tx`] or [`Indexer::index_txout`].
177+
/// The lookahead is the number of scripts to cache ahead of the last revealed script index. This
178+
/// is useful to find outputs you own when processing block data that lie beyond the last revealed
179+
/// index. In certain situations, such as when performing an initial scan of the blockchain during
180+
/// wallet import, it may be uncertain or unknown what the last revealed index is.
180181
///
181182
/// # Panics
182183
///

crates/chain/src/lib.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,3 @@ pub mod collections {
100100

101101
/// How many confirmations are needed f or a coinbase output to be spent.
102102
pub const COINBASE_MATURITY: u32 = 100;
103-
104-
impl<A, IA> From<indexed_tx_graph::ChangeSet<A, IA>>
105-
for (local_chain::ChangeSet, indexed_tx_graph::ChangeSet<A, IA>)
106-
{
107-
fn from(indexed_changeset: indexed_tx_graph::ChangeSet<A, IA>) -> Self {
108-
(local_chain::ChangeSet::default(), indexed_changeset)
109-
}
110-
}

crates/chain/src/spk_txout_index.rs

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -53,35 +53,19 @@ impl<I> Default for SpkTxOutIndex<I> {
5353
}
5454

5555
impl<I: Clone + Ord> Indexer for SpkTxOutIndex<I> {
56-
type ChangeSet = BTreeSet<I>;
56+
type ChangeSet = ();
5757

5858
fn index_txout(&mut self, outpoint: OutPoint, txout: &TxOut) -> Self::ChangeSet {
59-
let spk_i = self.spk_indices.get(&txout.script_pubkey);
60-
let mut scanned_indices = BTreeSet::new();
61-
if let Some(spk_i) = spk_i {
62-
self.txouts.insert(outpoint, (spk_i.clone(), txout.clone()));
63-
self.spk_txouts.insert((spk_i.clone(), outpoint));
64-
self.unused.remove(spk_i);
65-
scanned_indices.insert(spk_i.clone());
66-
}
67-
scanned_indices
59+
self.scan_txout(outpoint, txout);
60+
Default::default()
6861
}
6962

7063
fn index_tx(&mut self, tx: &Transaction) -> Self::ChangeSet {
71-
let mut scanned_indices = BTreeSet::new();
72-
73-
for (i, txout) in tx.output.iter().enumerate() {
74-
let op = OutPoint::new(tx.txid(), i as u32);
75-
let mut txout_indices = self.index_txout(op, txout);
76-
scanned_indices.append(&mut txout_indices);
77-
}
78-
79-
scanned_indices
64+
self.scan(tx);
65+
Default::default()
8066
}
8167

82-
fn initial_changeset(&self) -> Self::ChangeSet {
83-
self.spks.keys().cloned().collect()
84-
}
68+
fn initial_changeset(&self) -> Self::ChangeSet {}
8569

8670
fn apply_changeset(&mut self, _changeset: Self::ChangeSet) {
8771
// This applies nothing.
@@ -93,6 +77,38 @@ impl<I: Clone + Ord> Indexer for SpkTxOutIndex<I> {
9377
}
9478

9579
impl<I: Clone + Ord> SpkTxOutIndex<I> {
80+
/// Scans a transaction's outputs for matching script pubkeys.
81+
///
82+
/// Typically, this is used in two situations:
83+
///
84+
/// 1. After loading transaction data from the disk, you may scan over all the txouts to restore all
85+
/// your txouts.
86+
/// 2. When getting new data from the chain, you usually scan it before incorporating it into your chain state.
87+
pub fn scan(&mut self, tx: &Transaction) -> BTreeSet<I> {
88+
let mut scanned_indices = BTreeSet::new();
89+
let txid = tx.txid();
90+
for (i, txout) in tx.output.iter().enumerate() {
91+
let op = OutPoint::new(txid, i as u32);
92+
if let Some(spk_i) = self.scan_txout(op, txout) {
93+
scanned_indices.insert(spk_i.clone());
94+
}
95+
}
96+
97+
scanned_indices
98+
}
99+
100+
/// Scan a single `TxOut` for a matching script pubkey and returns the index that matches the
101+
/// script pubkey (if any).
102+
pub fn scan_txout(&mut self, op: OutPoint, txout: &TxOut) -> Option<&I> {
103+
let spk_i = self.spk_indices.get(&txout.script_pubkey);
104+
if let Some(spk_i) = spk_i {
105+
self.txouts.insert(op, (spk_i.clone(), txout.clone()));
106+
self.spk_txouts.insert((spk_i.clone(), op));
107+
self.unused.remove(spk_i);
108+
}
109+
spk_i
110+
}
111+
96112
/// Get a reference to the set of indexed outpoints.
97113
pub fn outpoints(&self) -> &BTreeSet<(I, OutPoint)> {
98114
&self.spk_txouts

0 commit comments

Comments
 (0)