From: 志宇 Date: Mon, 29 May 2023 05:20:12 +0000 (+0800) Subject: [wallet_redesign] Clean up and document address methods X-Git-Tag: v1.0.0-alpha.1~6^2~1 X-Git-Url: http://internal-gitweb-vhost/script/%22https:/struct.CommandStringError.html?a=commitdiff_plain;h=cff92111d500fbcdd70015c03bf57b386d473fba;p=bdk [wallet_redesign] Clean up and document address methods --- diff --git a/crates/bdk/src/types.rs b/crates/bdk/src/types.rs index 870734d6..e21bef90 100644 --- a/crates/bdk/src/types.rs +++ b/crates/bdk/src/types.rs @@ -22,9 +22,9 @@ use serde::{Deserialize, Serialize}; /// Types of keychains #[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] pub enum KeychainKind { - /// External + /// External keychain, used for deriving recipient addresses. External = 0, - /// Internal, usually used for change outputs + /// Internal keychain, used for deriving change addresses. Internal = 1, } diff --git a/crates/bdk/src/wallet/mod.rs b/crates/bdk/src/wallet/mod.rs index 33546ce0..4bee9be8 100644 --- a/crates/bdk/src/wallet/mod.rs +++ b/crates/bdk/src/wallet/mod.rs @@ -273,7 +273,8 @@ impl Wallet { where D: PersistBackend, { - self._get_address(address_index, KeychainKind::External) + self._get_address(KeychainKind::External, address_index) + .expect("persistence backend must not fail") } /// Return a derived address using the internal (change) descriptor. @@ -287,50 +288,63 @@ impl Wallet { where D: PersistBackend, { - self._get_address(address_index, KeychainKind::Internal) + self._get_address(KeychainKind::Internal, address_index) + .expect("persistence backend must not fail") } - fn _get_address(&mut self, address_index: AddressIndex, keychain: KeychainKind) -> AddressInfo + /// Return a derived address using the specified `keychain` (external/internal). + /// + /// If `keychain` is [`KeychainKind::External`], external addresses will be derived (used for + /// receiving funds). + /// + /// If `keychain` is [`KeychainKind::Internal`], internal addresses will be derived (used for + /// creating change outputs). If the wallet does not have an internal keychain, it will use the + /// external keychain to derive change outputs. + /// + /// See [`AddressIndex`] for available address index selection strategies. If none of the keys + /// in the descriptor are derivable (i.e. does not end with /*) then the same address will + /// always be returned for any [`AddressIndex`]. + fn _get_address( + &mut self, + keychain: KeychainKind, + address_index: AddressIndex, + ) -> Result where D: PersistBackend, { let keychain = self.map_keychain(keychain); let txout_index = &mut self.indexed_graph.index; - let (index, spk) = match address_index { + let (index, spk, additions) = match address_index { AddressIndex::New => { let ((index, spk), index_additions) = txout_index.reveal_next_spk(&keychain); - let spk = spk.clone(); - - self.persist - .stage(ChangeSet::from(IndexedAdditions::from(index_additions))); - self.persist.commit().expect("TODO"); - (index, spk) + (index, spk.clone(), Some(index_additions)) } AddressIndex::LastUnused => { - let index = txout_index.last_revealed_index(&keychain); - match index { - Some(index) if !txout_index.is_used(&(keychain, index)) => ( - index, - txout_index - .spk_at_index(&(keychain, index)) - .expect("must exist") - .clone(), - ), - _ => return self._get_address(AddressIndex::New, keychain), - } + let ((index, spk), index_additions) = txout_index.next_unused_spk(&keychain); + (index, spk.clone(), Some(index_additions)) + } + AddressIndex::Peek(index) => { + let (index, spk) = txout_index + .spks_of_keychain(&keychain) + .take(index as usize + 1) + .last() + .unwrap(); + (index, spk, None) } - AddressIndex::Peek(index) => txout_index - .spks_of_keychain(&keychain) - .take(index as usize + 1) - .last() - .unwrap(), }; - AddressInfo { + + if let Some(additions) = additions { + self.persist + .stage(ChangeSet::from(IndexedAdditions::from(additions))); + self.persist.commit()?; + } + + Ok(AddressInfo { index, address: Address::from_script(&spk, self.network) .expect("descriptor must have address form"), keychain, - } + }) } /// Return whether or not a `script` is part of this wallet (either internal or external)