]> Untitled Git - bdk/commitdiff
Merge branch 'master' into remove-blockchain-from-wallet
authorLLFourn <lloyd.fourn@gmail.com>
Thu, 3 Mar 2022 02:13:45 +0000 (13:13 +1100)
committerLLFourn <lloyd.fourn@gmail.com>
Thu, 3 Mar 2022 02:13:45 +0000 (13:13 +1100)
1  2 
CHANGELOG.md
src/testutils/blockchain_tests.rs
src/wallet/mod.rs

diff --cc CHANGELOG.md
index 319fb628850d7fdc334deb2782a51ded244e794b,4b35dd130324c492ed64660e2591015c4a576912..cad538d58b7d86d2f13b9fc81cef54128c382370
@@@ -8,18 -8,9 +8,20 @@@ and this project adheres to [Semantic V
  
  - Removed default verification from `wallet::sync`. sync-time verification is added in `script_sync` and is activated by `verify` feature flag.
  - `verify` flag removed from `TransactionDetails`.
+ - Add `get_internal_address` to allow you to get internal addresses just as you get external addresses.
+ - added `ensure_addresses_cached` to `Wallet` to let offline wallets load and cache addresses in their database
  
 +### Sync API change
 +
 +To decouple the `Wallet` from the `Blockchain` we've made major changes:
 +
 +- Removed `Blockchain` from Wallet.
 +- Removed `Wallet::broadcast` (just use `Blockchain::broadcast`)
 +- Depreciated `Wallet::new_offline` (all wallets are offline now)
 +- Changed `Wallet::sync` to take a `Blockchain`.
 +- Stop making a request for the block height when calling `Wallet:new`.
 +- Added `SyncOptions` to capture extra (future) arguments to `Wallet::sync`.
 +
  ## [v0.16.1] - [v0.16.0]
  
  - Pin tokio dependency version to ~1.14 to prevent errors due to their new MSRV 1.49.0
index b54da105ceba45bf1af9dcda944b4a4e6835d5ae,30d926cee4d83398efc9f2330fee6499c59c8ae1..6ac91e88fc3f209407c0e11e94032cd8705726a3
@@@ -817,11 -815,11 +817,11 @@@ macro_rules! bdk_blockchain_tests 
  
                  let mut builder = wallet.build_fee_bump(details.txid).unwrap();
                  builder.fee_rate(FeeRate::from_sat_per_vb(2.1));
-                 let (mut new_psbt, new_details) = builder.finish().unwrap();
+                 let (mut new_psbt, new_details) = builder.finish().expect("fee bump tx");
                  let finalized = wallet.sign(&mut new_psbt, Default::default()).unwrap();
                  assert!(finalized, "Cannot finalize transaction");
 -                wallet.broadcast(&new_psbt.extract_tx()).unwrap();
 -                wallet.sync(noop_progress(), None).unwrap();
 +                blockchain.broadcast(&new_psbt.extract_tx()).unwrap();
 +                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
                  assert_eq!(wallet.get_balance().unwrap(), 50_000 - new_details.fee.unwrap_or(0) - 5_000, "incorrect balance from fees after bump");
                  assert_eq!(wallet.get_balance().unwrap(), new_details.received, "incorrect balance from received after bump");
  
index 4006ccb299d962d6e05ab7c588539a1afcd80bf5,93a0d01e2b239e21b89a1ea2efc6e47b97a44638..97f7bbb820280a9e2c7ad1f58e7a0016696b9b68
@@@ -234,13 -175,74 +234,13 @@@ wher
      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?
@@@ -3953,6 -4015,48 +3982,48 @@@ pub(crate) mod test 
          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