@@ -30,7 +30,6 @@ use bitcoin::util::psbt::Input;
30
30
use bitcoin:: util:: psbt:: PartiallySignedTransaction as Psbt ;
31
31
use bitcoin:: { Address , Network , OutPoint , Script , SigHashType , Transaction , TxOut , Txid } ;
32
32
33
- use miniscript:: descriptor:: Descriptor ;
34
33
use miniscript:: descriptor:: DescriptorTrait ;
35
34
use miniscript:: psbt:: PsbtInputSatisfier ;
36
35
@@ -62,9 +61,9 @@ use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils, SyncTime};
62
61
use crate :: descriptor:: derived:: AsDerived ;
63
62
use crate :: descriptor:: policy:: BuildSatisfaction ;
64
63
use crate :: descriptor:: {
65
- get_checksum, into_wallet_descriptor_checked, DerivedDescriptor , DerivedDescriptorKey ,
66
- DerivedDescriptorMeta , DescriptorMeta , DescriptorScripts , ExtendedDescriptor , ExtractPolicy ,
67
- IntoWalletDescriptor , Policy , XKeyUtils ,
64
+ get_checksum, into_wallet_descriptor_checked, DerivedDescriptor , DerivedDescriptorMeta ,
65
+ DescriptorMeta , DescriptorScripts , ExtendedDescriptor , ExtractPolicy , IntoWalletDescriptor ,
66
+ Policy , XKeyUtils ,
68
67
} ;
69
68
use crate :: error:: Error ;
70
69
use crate :: psbt:: PsbtUtils ;
@@ -261,95 +260,26 @@ where
261
260
. map_err ( |_| Error :: ScriptDoesntHaveAddressForm )
262
261
}
263
262
264
- // Return vector of unused address indexes
265
- fn get_unused_key_indexes ( & self , keychain : KeychainKind ) -> Result < Vec < u32 > , Error > {
266
- let current_index = self . fetch_index ( keychain) ?;
267
-
268
- let derived_keys: Vec < Descriptor < DerivedDescriptorKey > > = ( 0 ..current_index + 1 )
269
- . map ( |i| {
270
- self . get_descriptor_for_keychain ( keychain)
271
- . as_derived ( i, & self . secp )
272
- } )
273
- . collect ( ) ;
274
-
275
- let unused_key_indexes: Vec < u32 > = derived_keys
276
- . iter ( )
277
- . cloned ( )
278
- . enumerate ( )
279
- . filter_map ( |( i, key) | {
280
- if !self
281
- . list_transactions ( true )
282
- . expect ( "getting transaction list" )
283
- . iter ( )
284
- . flat_map ( |tx_details| tx_details. transaction . as_ref ( ) )
285
- . flat_map ( |tx| tx. output . iter ( ) )
286
- . any ( |o| o. script_pubkey == key. script_pubkey ( ) )
287
- {
288
- Some ( i as u32 )
289
- } else {
290
- None
291
- }
292
- } )
293
- . collect ( ) ;
294
-
295
- Ok ( unused_key_indexes)
263
+ // Return whether this address has been used in a transaction
264
+ fn has_address_been_used ( & self , script_pk : & Script ) -> bool {
265
+ let txns = self . list_transactions ( true ) . unwrap_or_else ( |_| vec ! [ ] ) ;
266
+ txns. iter ( )
267
+ . flat_map ( |tx_details| tx_details. transaction . as_ref ( ) )
268
+ . flat_map ( |tx| tx. output . iter ( ) )
269
+ . any ( |o| o. script_pubkey == * script_pk)
296
270
}
297
271
298
272
// Return the the last previously derived address for `keychain` if it has not been used in a
299
273
// received transaction. Otherwise return a new address using [`Wallet::get_new_address`].
300
274
fn get_last_unused_address ( & self , keychain : KeychainKind ) -> Result < AddressInfo , Error > {
301
- let mut unused_key_indexes = self . get_unused_key_indexes ( keychain) ?;
302
- match unused_key_indexes. pop ( ) {
303
- None => self . get_new_address ( keychain) ,
304
- Some ( address_index) => {
305
- let derived_key = self
306
- . get_descriptor_for_keychain ( keychain)
307
- . as_derived ( address_index, & self . secp ) ;
308
-
309
- let script_pubkey = derived_key. script_pubkey ( ) ;
310
-
311
- let found_used = self
312
- . list_transactions ( true ) ?
313
- . iter ( )
314
- . flat_map ( |tx_details| tx_details. transaction . as_ref ( ) )
315
- . flat_map ( |tx| tx. output . iter ( ) )
316
- . any ( |o| o. script_pubkey == script_pubkey) ;
317
-
318
- if found_used {
319
- self . get_new_address ( keychain)
320
- } else {
321
- derived_key
322
- . address ( self . network )
323
- . map ( |address| AddressInfo {
324
- address,
325
- index : address_index,
326
- keychain,
327
- } )
328
- . map_err ( |_| Error :: ScriptDoesntHaveAddressForm )
329
- }
330
- }
331
- }
275
+ let mut unused_addresses = self . get_batch_unused_addresses ( 1 , false , keychain) ?;
276
+ Ok ( unused_addresses. remove ( 0 ) )
332
277
}
333
278
334
279
// Return the the first address in the keychain which has not been a recipient of a transaction
335
280
fn get_first_unused_address ( & self , keychain : KeychainKind ) -> Result < AddressInfo , Error > {
336
- let unused_key_indexes = self . get_unused_key_indexes ( keychain) ?;
337
- if unused_key_indexes. is_empty ( ) {
338
- self . get_new_address ( keychain)
339
- } else {
340
- let derived_key = self
341
- . get_descriptor_for_keychain ( keychain)
342
- . as_derived ( unused_key_indexes[ 0 ] , & self . secp ) ;
343
-
344
- derived_key
345
- . address ( self . network )
346
- . map ( |address| AddressInfo {
347
- address,
348
- index : unused_key_indexes[ 0 ] ,
349
- keychain,
350
- } )
351
- . map_err ( |_| Error :: ScriptDoesntHaveAddressForm )
352
- }
281
+ let mut unused_addresses = self . get_batch_unused_addresses ( 1 , true , keychain) ?;
282
+ Ok ( unused_addresses. remove ( 0 ) )
353
283
}
354
284
355
285
// Return derived address for the descriptor of given [`KeychainKind`] at a specific index
@@ -463,31 +393,54 @@ where
463
393
pub fn get_batch_unused_addresses (
464
394
& self ,
465
395
n : usize ,
396
+ from_front : bool ,
466
397
keychain : KeychainKind ,
467
398
) -> Result < Vec < AddressInfo > , Error > {
468
- let unused_key_indexes = self . get_unused_key_indexes ( keychain) ?;
469
- let mut addresses = unused_key_indexes
470
- . iter ( )
471
- . map ( |i| {
472
- let derived_key = self
473
- . get_descriptor_for_keychain ( keychain)
474
- . as_derived ( * i, & self . secp ) ;
475
-
476
- derived_key
477
- . address ( self . network )
478
- . map ( |address| AddressInfo {
479
- address,
480
- index : * i,
481
- keychain,
482
- } )
483
- . map_err ( |_| Error :: ScriptDoesntHaveAddressForm )
484
- } )
485
- . take ( n)
486
- . collect :: < Result < Vec < _ > , _ > > ( ) ?;
487
- for _ in 0 ..( n - addresses. len ( ) ) {
488
- addresses. push ( self . get_new_address ( keychain) ?)
399
+ let script_pubkeys = self
400
+ . database
401
+ . borrow ( )
402
+ . iter_script_pubkeys ( Some ( keychain) )
403
+ . unwrap_or_else ( |_| vec ! [ ] ) ;
404
+
405
+ let current_address_index = self . fetch_index ( keychain) ? as usize ;
406
+ let check_indexes = if from_front {
407
+ ( 0 ..=current_address_index) . collect :: < Vec < _ > > ( )
408
+ } else {
409
+ ( 0 ..=current_address_index) . rev ( ) . collect :: < Vec < _ > > ( )
410
+ } ;
411
+
412
+ let mut unused_addresses = vec ! [ ] ;
413
+ for i in check_indexes {
414
+ // if we have made a pubkey at this index, check whether the address has been used.
415
+ if i < script_pubkeys. len ( ) {
416
+ let script_pk = & script_pubkeys[ i] ;
417
+ if self . has_address_been_used ( script_pk) {
418
+ continue ;
419
+ }
420
+ }
421
+ if let Ok ( unused_address) = self
422
+ . get_descriptor_for_keychain ( keychain)
423
+ . as_derived ( i as u32 , & self . secp )
424
+ . address ( self . network )
425
+ . map ( |address| AddressInfo {
426
+ address,
427
+ index : i as u32 ,
428
+ keychain,
429
+ } )
430
+ . map_err ( |_| Error :: ScriptDoesntHaveAddressForm )
431
+ {
432
+ unused_addresses. push ( unused_address) ;
433
+ }
434
+
435
+ if unused_addresses. len ( ) >= n {
436
+ break ;
437
+ }
438
+ }
439
+
440
+ for _ in 0 ..( n - unused_addresses. len ( ) ) {
441
+ unused_addresses. push ( self . get_new_address ( keychain) ?)
489
442
}
490
- Ok ( addresses )
443
+ Ok ( unused_addresses )
491
444
}
492
445
493
446
/// Return whether or not a `script` is part of this wallet (either internal or external)
@@ -4029,7 +3982,7 @@ pub(crate) mod test {
4029
3982
4030
3983
assert_eq ! (
4031
3984
wallet
4032
- . get_batch_unused_addresses( 3 , KeychainKind :: External )
3985
+ . get_batch_unused_addresses( 3 , true , KeychainKind :: External )
4033
3986
. unwrap( ) ,
4034
3987
vec![
4035
3988
AddressInfo {
0 commit comments