pub fn network(&self) -> Network {
self.network
}
-}
-
-/// The address index selection strategy to use to derived an address from the wallet's external
-/// descriptor. See [`Wallet::get_address`]. If you're unsure which one to use use `WalletIndex::New`.
-#[derive(Debug)]
-pub enum AddressIndex {
- /// Return a new address after incrementing the current descriptor index.
- New,
- /// Return the address for the current descriptor index if it has not been used in a received
- /// transaction. Otherwise return a new address as with [`AddressIndex::New`].
- ///
- /// Use with caution, if the wallet has not yet detected an address has been used it could
- /// return an already used address. This function is primarily meant for situations where the
- /// caller is untrusted; for example when deriving donation addresses on-demand for a public
- /// web page.
- LastUnused,
- /// Return the address for a specific descriptor index. Does not change the current descriptor
- /// index used by `AddressIndex::New` and `AddressIndex::LastUsed`.
- ///
- /// Use with caution, if an index is given that is less than the current descriptor index
- /// then the returned address may have already been used.
- Peek(u32),
- /// Return the address for a specific descriptor index and reset the current descriptor index
- /// used by `AddressIndex::New` and `AddressIndex::LastUsed` to this value.
- ///
- /// Use with caution, if an index is given that is less than the current descriptor index
- /// then the returned address and subsequent addresses returned by calls to `AddressIndex::New`
- /// and `AddressIndex::LastUsed` may have already been used. Also if the index is reset to a
- /// value earlier than the [`crate::blockchain::Blockchain`] stop_gap (default is 20) then a
- /// larger stop_gap should be used to monitor for all possibly used addresses.
- Reset(u32),
-}
-
-/// A derived address and the index it was found at
-/// For convenience this automatically derefs to `Address`
-#[derive(Debug, PartialEq)]
-pub struct AddressInfo {
- /// Child index of this address
- pub index: u32,
- /// Address
- pub address: Address,
-}
-
-impl Deref for AddressInfo {
- type Target = Address;
-
- fn deref(&self) -> &Self::Target {
- &self.address
- }
-}
-
-impl fmt::Display for AddressInfo {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "{}", self.address)
- }
-}
-// offline actions, always available
-impl<B, D> Wallet<B, D>
-where
- D: BatchDatabase,
-{
- // Return a newly derived address for the specified `keychain`.
+ // Return a newly derived address using the external descriptor
- fn get_new_address(&self) -> Result<AddressInfo, Error> {
- let incremented_index = self.fetch_and_increment_index(KeychainKind::External)?;
+ fn get_new_address(&self, keychain: KeychainKind) -> Result<AddressInfo, Error> {
+ let incremented_index = self.fetch_and_increment_index(keychain)?;
let address_result = self
- .descriptor
+ .get_descriptor_for_keychain(keychain)
.as_derived(incremented_index, &self.secp)
.address(self.network);
) -> Result<(), Error> {
debug!("Begin sync...");
- let mut run_setup = false;
+ let SyncOptions {
+ max_addresses,
+ progress,
+ } = sync_opts;
+ let progress = progress.unwrap_or_else(|| Box::new(NoopProgress));
+
- let max_address = match self.descriptor.is_deriveable() {
- false => 0,
- true => max_addresses.unwrap_or(CACHE_ADDR_BATCH_SIZE),
- };
- debug!("max_address {}", max_address);
- if self
- .database
- .borrow()
- .get_script_pubkey_from_path(KeychainKind::External, max_address.saturating_sub(1))?
- .is_none()
- {
- debug!("caching external addresses");
- run_setup = true;
- self.cache_addresses(KeychainKind::External, 0, max_address)?;
- }
-
- if let Some(change_descriptor) = &self.change_descriptor {
- let max_address = match change_descriptor.is_deriveable() {
- false => 0,
- true => max_addresses.unwrap_or(CACHE_ADDR_BATCH_SIZE),
- };
-
- if self
- .database
- .borrow()
- .get_script_pubkey_from_path(KeychainKind::Internal, max_address.saturating_sub(1))?
- .is_none()
- {
- debug!("caching internal addresses");
- run_setup = true;
- self.cache_addresses(KeychainKind::Internal, 0, max_address)?;
- }
- }
+ let run_setup =
- self.ensure_addresses_cached(max_address_param.unwrap_or(CACHE_ADDR_BATCH_SIZE))?;
++ self.ensure_addresses_cached(max_addresses.unwrap_or(CACHE_ADDR_BATCH_SIZE))?;
debug!("run_setup: {}", run_setup);
// TODO: what if i generate an address first and cache some addresses?
builder.add_recipient(addr.script_pubkey(), 45_000);
builder.finish().unwrap();
}
- let wallet = Wallet::new_offline(
+
+ #[test]
+ fn test_get_address() {
+ use crate::descriptor::template::Bip84;
+ let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
- let wallet = Wallet::new_offline(
++ let wallet = Wallet::new(
+ Bip84(key, KeychainKind::External),
+ Some(Bip84(key, KeychainKind::Internal)),
+ Network::Regtest,
+ MemoryDatabase::default(),
+ )
+ .unwrap();
+
+ assert_eq!(
+ wallet.get_address(AddressIndex::New).unwrap().address,
+ Address::from_str("bcrt1qkmvk2nadgplmd57ztld8nf8v2yxkzmdvwtjf8s").unwrap()
+ );
+ assert_eq!(
+ wallet
+ .get_internal_address(AddressIndex::New)
+ .unwrap()
+ .address,
+ Address::from_str("bcrt1qtrwtz00wxl69e5xex7amy4xzlxkaefg3gfdkxa").unwrap()
+ );
+
++ let wallet = Wallet::new(
+ Bip84(key, KeychainKind::External),
+ None,
+ Network::Regtest,
+ MemoryDatabase::default(),
+ )
+ .unwrap();
+
+ assert_eq!(
+ wallet
+ .get_internal_address(AddressIndex::New)
+ .unwrap()
+ .address,
+ Address::from_str("bcrt1qkmvk2nadgplmd57ztld8nf8v2yxkzmdvwtjf8s").unwrap(),
+ "when there's no internal descriptor it should just use external"
+ );
+ }
}
/// Deterministically generate a unique name given the descriptors defining the wallet