@@ -237,12 +237,12 @@ impl<B, D> Wallet<B, D>
237
237
where
238
238
D : BatchDatabase ,
239
239
{
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 ) ?;
243
243
244
244
let address_result = self
245
- . descriptor
245
+ . get_descriptor_for_keychain ( keychain )
246
246
. as_derived ( incremented_index, & self . secp )
247
247
. address ( self . network ) ;
248
248
@@ -254,12 +254,14 @@ where
254
254
. map_err ( |_| Error :: ScriptDoesntHaveAddressForm )
255
255
}
256
256
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 ) ?;
261
261
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 ) ;
263
265
264
266
let script_pubkey = derived_key. script_pubkey ( ) ;
265
267
@@ -271,7 +273,7 @@ where
271
273
. any ( |o| o. script_pubkey == script_pubkey) ;
272
274
273
275
if found_used {
274
- self . get_new_address ( )
276
+ self . get_new_address ( keychain )
275
277
} else {
276
278
derived_key
277
279
. address ( self . network )
@@ -283,21 +285,21 @@ where
283
285
}
284
286
}
285
287
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 )
289
291
. as_derived ( index, & self . secp )
290
292
. address ( self . network )
291
293
. map ( |address| AddressInfo { index, address } )
292
294
. map_err ( |_| Error :: ScriptDoesntHaveAddressForm )
293
295
}
294
296
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
296
298
// 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) ?;
299
301
300
- self . descriptor
302
+ self . get_descriptor_for_keychain ( keychain )
301
303
. as_derived ( index, & self . secp )
302
304
. address ( self . network )
303
305
. map ( |address| AddressInfo { index, address } )
@@ -308,11 +310,30 @@ where
308
310
/// available address index selection strategies. If none of the keys in the descriptor are derivable
309
311
/// (ie. does not end with /*) then the same address will always be returned for any [`AddressIndex`].
310
312
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 > {
311
332
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 ) ,
316
337
}
317
338
}
318
339
@@ -662,7 +683,10 @@ where
662
683
let mut drain_output = {
663
684
let script_pubkey = match params. drain_to {
664
685
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 ( ) ,
666
690
} ;
667
691
668
692
TxOut {
@@ -1091,13 +1115,6 @@ where
1091
1115
. map ( |( desc, child) | desc. as_derived ( child, & self . secp ) ) )
1092
1116
}
1093
1117
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
-
1101
1118
fn fetch_and_increment_index ( & self , keychain : KeychainKind ) -> Result < u32 , Error > {
1102
1119
let ( descriptor, keychain) = self . _get_descriptor_for_keychain ( keychain) ;
1103
1120
let index = match descriptor. is_deriveable ( ) {
@@ -3987,6 +4004,48 @@ pub(crate) mod test {
3987
4004
builder. add_recipient ( addr. script_pubkey ( ) , 45_000 ) ;
3988
4005
builder. finish ( ) . unwrap ( ) ;
3989
4006
}
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
+ }
3990
4049
}
3991
4050
3992
4051
/// Deterministically generate a unique name given the descriptors defining the wallet
0 commit comments