@@ -237,12 +237,12 @@ impl<B, D> Wallet<B, D>
237237where
238238 D : BatchDatabase ,
239239{
240- // Return a newly derived address using the external descriptor
241- fn get_new_address ( & self ) -> Result < AddressInfo , Error > {
242- let incremented_index = self . fetch_and_increment_index ( KeychainKind :: External ) ?;
240+ // Return a newly derived address for the specified `keychain`.
241+ fn get_new_address ( & self , keychain : KeychainKind ) -> Result < AddressInfo , Error > {
242+ let incremented_index = self . fetch_and_increment_index ( keychain ) ?;
243243
244244 let address_result = self
245- . descriptor
245+ . get_descriptor_for_keychain ( keychain )
246246 . as_derived ( incremented_index, & self . secp )
247247 . address ( self . network ) ;
248248
@@ -254,12 +254,14 @@ where
254254 . map_err ( |_| Error :: ScriptDoesntHaveAddressForm )
255255 }
256256
257- // Return the the last previously derived address if it has not been used in a received
258- // transaction. Otherwise return a new address using [`Wallet::get_new_address`].
259- fn get_unused_address ( & self ) -> Result < AddressInfo , Error > {
260- let current_index = self . fetch_index ( KeychainKind :: External ) ?;
257+ // Return the the last previously derived address for `keychain` if it has not been used in a
258+ // received transaction. Otherwise return a new address using [`Wallet::get_new_address`].
259+ fn get_unused_address ( & self , keychain : KeychainKind ) -> Result < AddressInfo , Error > {
260+ let current_index = self . fetch_index ( keychain ) ?;
261261
262- let derived_key = self . descriptor . as_derived ( current_index, & self . secp ) ;
262+ let derived_key = self
263+ . get_descriptor_for_keychain ( keychain)
264+ . as_derived ( current_index, & self . secp ) ;
263265
264266 let script_pubkey = derived_key. script_pubkey ( ) ;
265267
@@ -271,7 +273,7 @@ where
271273 . any ( |o| o. script_pubkey == script_pubkey) ;
272274
273275 if found_used {
274- self . get_new_address ( )
276+ self . get_new_address ( keychain )
275277 } else {
276278 derived_key
277279 . address ( self . network )
@@ -283,21 +285,21 @@ where
283285 }
284286 }
285287
286- // Return derived address for the external descriptor at a specific index
287- fn peek_address ( & self , index : u32 ) -> Result < AddressInfo , Error > {
288- self . descriptor
288+ // Return derived address for the descriptor of given [`KeychainKind`] at a specific index
289+ fn peek_address ( & self , index : u32 , keychain : KeychainKind ) -> Result < AddressInfo , Error > {
290+ self . get_descriptor_for_keychain ( keychain )
289291 . as_derived ( index, & self . secp )
290292 . address ( self . network )
291293 . map ( |address| AddressInfo { index, address } )
292294 . map_err ( |_| Error :: ScriptDoesntHaveAddressForm )
293295 }
294296
295- // Return derived address for the external descriptor at a specific index and reset current
297+ // Return derived address for `keychain` at a specific index and reset current
296298 // address index
297- fn reset_address ( & self , index : u32 ) -> Result < AddressInfo , Error > {
298- self . set_index ( KeychainKind :: External , index) ?;
299+ fn reset_address ( & self , index : u32 , keychain : KeychainKind ) -> Result < AddressInfo , Error > {
300+ self . set_index ( keychain , index) ?;
299301
300- self . descriptor
302+ self . get_descriptor_for_keychain ( keychain )
301303 . as_derived ( index, & self . secp )
302304 . address ( self . network )
303305 . map ( |address| AddressInfo { index, address } )
@@ -308,11 +310,30 @@ where
308310 /// available address index selection strategies. If none of the keys in the descriptor are derivable
309311 /// (ie. does not end with /*) then the same address will always be returned for any [`AddressIndex`].
310312 pub fn get_address ( & self , address_index : AddressIndex ) -> Result < AddressInfo , Error > {
313+ self . _get_address ( address_index, KeychainKind :: External )
314+ }
315+
316+ /// Return a derived address using the internal (change) descriptor.
317+ ///
318+ /// If the wallet doesn't have an internal descriptor it will use the external descriptor.
319+ ///
320+ /// see [`AddressIndex`] for available address index selection strategies. If none of the keys
321+ /// in the descriptor are derivable (ie. does not end with /*) then the same address will always
322+ /// be returned for any [`AddressIndex`].
323+ pub fn get_internal_address ( & self , address_index : AddressIndex ) -> Result < AddressInfo , Error > {
324+ self . _get_address ( address_index, KeychainKind :: Internal )
325+ }
326+
327+ fn _get_address (
328+ & self ,
329+ address_index : AddressIndex ,
330+ keychain : KeychainKind ,
331+ ) -> Result < AddressInfo , Error > {
311332 match address_index {
312- AddressIndex :: New => self . get_new_address ( ) ,
313- AddressIndex :: LastUnused => self . get_unused_address ( ) ,
314- AddressIndex :: Peek ( index) => self . peek_address ( index) ,
315- AddressIndex :: Reset ( index) => self . reset_address ( index) ,
333+ AddressIndex :: New => self . get_new_address ( keychain ) ,
334+ AddressIndex :: LastUnused => self . get_unused_address ( keychain ) ,
335+ AddressIndex :: Peek ( index) => self . peek_address ( index, keychain ) ,
336+ AddressIndex :: Reset ( index) => self . reset_address ( index, keychain ) ,
316337 }
317338 }
318339
@@ -662,7 +683,10 @@ where
662683 let mut drain_output = {
663684 let script_pubkey = match params. drain_to {
664685 Some ( ref drain_recipient) => drain_recipient. clone ( ) ,
665- None => self . get_change_address ( ) ?,
686+ None => self
687+ . get_internal_address ( AddressIndex :: New ) ?
688+ . address
689+ . script_pubkey ( ) ,
666690 } ;
667691
668692 TxOut {
@@ -1091,13 +1115,6 @@ where
10911115 . map ( |( desc, child) | desc. as_derived ( child, & self . secp ) ) )
10921116 }
10931117
1094- fn get_change_address ( & self ) -> Result < Script , Error > {
1095- let ( desc, keychain) = self . _get_descriptor_for_keychain ( KeychainKind :: Internal ) ;
1096- let index = self . fetch_and_increment_index ( keychain) ?;
1097-
1098- Ok ( desc. as_derived ( index, & self . secp ) . script_pubkey ( ) )
1099- }
1100-
11011118 fn fetch_and_increment_index ( & self , keychain : KeychainKind ) -> Result < u32 , Error > {
11021119 let ( descriptor, keychain) = self . _get_descriptor_for_keychain ( keychain) ;
11031120 let index = match descriptor. is_deriveable ( ) {
@@ -3987,6 +4004,48 @@ pub(crate) mod test {
39874004 builder. add_recipient ( addr. script_pubkey ( ) , 45_000 ) ;
39884005 builder. finish ( ) . unwrap ( ) ;
39894006 }
4007+
4008+ #[ test]
4009+ fn test_get_address ( ) {
4010+ use crate :: descriptor:: template:: Bip84 ;
4011+ let key = bitcoin:: util:: bip32:: ExtendedPrivKey :: from_str ( "tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy" ) . unwrap ( ) ;
4012+ let wallet = Wallet :: new_offline (
4013+ Bip84 ( key, KeychainKind :: External ) ,
4014+ Some ( Bip84 ( key, KeychainKind :: Internal ) ) ,
4015+ Network :: Regtest ,
4016+ MemoryDatabase :: default ( ) ,
4017+ )
4018+ . unwrap ( ) ;
4019+
4020+ assert_eq ! (
4021+ wallet. get_address( AddressIndex :: New ) . unwrap( ) . address,
4022+ Address :: from_str( "bcrt1qkmvk2nadgplmd57ztld8nf8v2yxkzmdvwtjf8s" ) . unwrap( )
4023+ ) ;
4024+ assert_eq ! (
4025+ wallet
4026+ . get_internal_address( AddressIndex :: New )
4027+ . unwrap( )
4028+ . address,
4029+ Address :: from_str( "bcrt1qtrwtz00wxl69e5xex7amy4xzlxkaefg3gfdkxa" ) . unwrap( )
4030+ ) ;
4031+
4032+ let wallet = Wallet :: new_offline (
4033+ Bip84 ( key, KeychainKind :: External ) ,
4034+ None ,
4035+ Network :: Regtest ,
4036+ MemoryDatabase :: default ( ) ,
4037+ )
4038+ . unwrap ( ) ;
4039+
4040+ assert_eq ! (
4041+ wallet
4042+ . get_internal_address( AddressIndex :: New )
4043+ . unwrap( )
4044+ . address,
4045+ Address :: from_str( "bcrt1qkmvk2nadgplmd57ztld8nf8v2yxkzmdvwtjf8s" ) . unwrap( ) ,
4046+ "when there's no internal descriptor it should just use external"
4047+ ) ;
4048+ }
39904049}
39914050
39924051/// Deterministically generate a unique name given the descriptors defining the wallet
0 commit comments