Skip to content

Commit cff9211

Browse files
committed
[wallet_redesign] Clean up and document address methods
1 parent a7668a2 commit cff9211

File tree

2 files changed

+44
-30
lines changed

2 files changed

+44
-30
lines changed

crates/bdk/src/types.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ use serde::{Deserialize, Serialize};
2222
/// Types of keychains
2323
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
2424
pub enum KeychainKind {
25-
/// External
25+
/// External keychain, used for deriving recipient addresses.
2626
External = 0,
27-
/// Internal, usually used for change outputs
27+
/// Internal keychain, used for deriving change addresses.
2828
Internal = 1,
2929
}
3030

crates/bdk/src/wallet/mod.rs

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,8 @@ impl<D> Wallet<D> {
273273
where
274274
D: PersistBackend<ChangeSet>,
275275
{
276-
self._get_address(address_index, KeychainKind::External)
276+
self._get_address(KeychainKind::External, address_index)
277+
.expect("persistence backend must not fail")
277278
}
278279

279280
/// Return a derived address using the internal (change) descriptor.
@@ -287,50 +288,63 @@ impl<D> Wallet<D> {
287288
where
288289
D: PersistBackend<ChangeSet>,
289290
{
290-
self._get_address(address_index, KeychainKind::Internal)
291+
self._get_address(KeychainKind::Internal, address_index)
292+
.expect("persistence backend must not fail")
291293
}
292294

293-
fn _get_address(&mut self, address_index: AddressIndex, keychain: KeychainKind) -> AddressInfo
295+
/// Return a derived address using the specified `keychain` (external/internal).
296+
///
297+
/// If `keychain` is [`KeychainKind::External`], external addresses will be derived (used for
298+
/// receiving funds).
299+
///
300+
/// If `keychain` is [`KeychainKind::Internal`], internal addresses will be derived (used for
301+
/// creating change outputs). If the wallet does not have an internal keychain, it will use the
302+
/// external keychain to derive change outputs.
303+
///
304+
/// See [`AddressIndex`] for available address index selection strategies. If none of the keys
305+
/// in the descriptor are derivable (i.e. does not end with /*) then the same address will
306+
/// always be returned for any [`AddressIndex`].
307+
fn _get_address(
308+
&mut self,
309+
keychain: KeychainKind,
310+
address_index: AddressIndex,
311+
) -> Result<AddressInfo, D::WriteError>
294312
where
295313
D: PersistBackend<ChangeSet>,
296314
{
297315
let keychain = self.map_keychain(keychain);
298316
let txout_index = &mut self.indexed_graph.index;
299-
let (index, spk) = match address_index {
317+
let (index, spk, additions) = match address_index {
300318
AddressIndex::New => {
301319
let ((index, spk), index_additions) = txout_index.reveal_next_spk(&keychain);
302-
let spk = spk.clone();
303-
304-
self.persist
305-
.stage(ChangeSet::from(IndexedAdditions::from(index_additions)));
306-
self.persist.commit().expect("TODO");
307-
(index, spk)
320+
(index, spk.clone(), Some(index_additions))
308321
}
309322
AddressIndex::LastUnused => {
310-
let index = txout_index.last_revealed_index(&keychain);
311-
match index {
312-
Some(index) if !txout_index.is_used(&(keychain, index)) => (
313-
index,
314-
txout_index
315-
.spk_at_index(&(keychain, index))
316-
.expect("must exist")
317-
.clone(),
318-
),
319-
_ => return self._get_address(AddressIndex::New, keychain),
320-
}
323+
let ((index, spk), index_additions) = txout_index.next_unused_spk(&keychain);
324+
(index, spk.clone(), Some(index_additions))
325+
}
326+
AddressIndex::Peek(index) => {
327+
let (index, spk) = txout_index
328+
.spks_of_keychain(&keychain)
329+
.take(index as usize + 1)
330+
.last()
331+
.unwrap();
332+
(index, spk, None)
321333
}
322-
AddressIndex::Peek(index) => txout_index
323-
.spks_of_keychain(&keychain)
324-
.take(index as usize + 1)
325-
.last()
326-
.unwrap(),
327334
};
328-
AddressInfo {
335+
336+
if let Some(additions) = additions {
337+
self.persist
338+
.stage(ChangeSet::from(IndexedAdditions::from(additions)));
339+
self.persist.commit()?;
340+
}
341+
342+
Ok(AddressInfo {
329343
index,
330344
address: Address::from_script(&spk, self.network)
331345
.expect("descriptor must have address form"),
332346
keychain,
333-
}
347+
})
334348
}
335349

336350
/// Return whether or not a `script` is part of this wallet (either internal or external)

0 commit comments

Comments
 (0)