@@ -345,10 +345,10 @@ pub trait CoinSelectionSource {
345
345
/// other claims, implementations must be willing to double spend their UTXOs. The choice of
346
346
/// which UTXOs to double spend is left to the implementation, but it must strive to keep the
347
347
/// set of other claims being double spent to a minimum.
348
- fn select_confirmed_utxos (
349
- & self , claim_id : ClaimId , must_spend : Vec < Input > , must_pay_to : & [ TxOut ] ,
348
+ fn select_confirmed_utxos < ' a > (
349
+ & ' a self , claim_id : ClaimId , must_spend : Vec < Input > , must_pay_to : & ' a [ TxOut ] ,
350
350
target_feerate_sat_per_1000_weight : u32 ,
351
- ) -> Result < CoinSelection , ( ) > ;
351
+ ) -> AsyncResult < ' a , CoinSelection > ;
352
352
/// Signs and provides the full witness for all inputs within the transaction known to the
353
353
/// trait (i.e., any provided via [`CoinSelectionSource::select_confirmed_utxos`]).
354
354
///
@@ -361,7 +361,7 @@ pub trait CoinSelectionSource {
361
361
/// provide a default implementation to [`CoinSelectionSource`].
362
362
pub trait WalletSource {
363
363
/// Returns all UTXOs, with at least 1 confirmation each, that are available to spend.
364
- fn list_confirmed_utxos ( & self ) -> Result < Vec < Utxo > , ( ) > ;
364
+ fn list_confirmed_utxos < ' a > ( & ' a self ) -> AsyncResult < ' a , Vec < Utxo > > ;
365
365
/// Returns a script to use for change above dust resulting from a successful coin selection
366
366
/// attempt.
367
367
fn get_change_script ( & self ) -> Result < ScriptBuf , ( ) > ;
@@ -482,40 +482,54 @@ where
482
482
}
483
483
}
484
484
485
- impl < W : Deref , L : Deref > CoinSelectionSource for Wallet < W , L >
485
+ impl < W : Deref + Sync , L : Deref + Sync > CoinSelectionSource for Wallet < W , L >
486
486
where
487
487
W :: Target : WalletSource ,
488
- L :: Target : Logger
488
+ L :: Target : Logger ,
489
489
{
490
- fn select_confirmed_utxos (
491
- & self , claim_id : ClaimId , must_spend : Vec < Input > , must_pay_to : & [ TxOut ] ,
490
+ fn select_confirmed_utxos < ' a > (
491
+ & ' a self , claim_id : ClaimId , must_spend : Vec < Input > , must_pay_to : & ' a [ TxOut ] ,
492
492
target_feerate_sat_per_1000_weight : u32 ,
493
- ) -> Result < CoinSelection , ( ) > {
494
- let utxos = self . source . list_confirmed_utxos ( ) ?;
495
- // TODO: Use fee estimation utils when we upgrade to bitcoin v0.30.0.
496
- const BASE_TX_SIZE : u64 = 4 /* version */ + 1 /* input count */ + 1 /* output count */ + 4 /* locktime */ ;
497
- let total_output_size: u64 = must_pay_to. iter ( ) . map ( |output|
498
- 8 /* value */ + 1 /* script len */ + output. script_pubkey . len ( ) as u64
499
- ) . sum ( ) ;
500
- let total_satisfaction_weight: u64 = must_spend. iter ( ) . map ( |input| input. satisfaction_weight ) . sum ( ) ;
501
- let total_input_weight = ( BASE_INPUT_WEIGHT * must_spend. len ( ) as u64 ) + total_satisfaction_weight;
502
-
503
- let preexisting_tx_weight = 2 /* segwit marker & flag */ + total_input_weight +
504
- ( ( BASE_TX_SIZE + total_output_size) * WITNESS_SCALE_FACTOR as u64 ) ;
505
- let input_amount_sat = must_spend. iter ( ) . map ( |input| input. previous_utxo . value ) . sum ( ) ;
506
- let target_amount_sat = must_pay_to. iter ( ) . map ( |output| output. value ) . sum ( ) ;
507
- let do_coin_selection = |force_conflicting_utxo_spend : bool , tolerate_high_network_feerates : bool | {
508
- log_debug ! ( self . logger, "Attempting coin selection targeting {} sat/kW (force_conflicting_utxo_spend = {}, tolerate_high_network_feerates = {})" ,
509
- target_feerate_sat_per_1000_weight, force_conflicting_utxo_spend, tolerate_high_network_feerates) ;
510
- self . select_confirmed_utxos_internal (
511
- & utxos, claim_id, force_conflicting_utxo_spend, tolerate_high_network_feerates,
512
- target_feerate_sat_per_1000_weight, preexisting_tx_weight, input_amount_sat, target_amount_sat,
513
- )
514
- } ;
515
- do_coin_selection ( false , false )
516
- . or_else ( |_| do_coin_selection ( false , true ) )
517
- . or_else ( |_| do_coin_selection ( true , false ) )
518
- . or_else ( |_| do_coin_selection ( true , true ) )
493
+ ) -> AsyncResult < ' a , CoinSelection > {
494
+ Box :: pin ( async move {
495
+ let utxos = self . source . list_confirmed_utxos ( ) . await ?;
496
+ // TODO: Use fee estimation utils when we upgrade to bitcoin v0.30.0.
497
+ const BASE_TX_SIZE : u64 = 4 /* version */ + 1 /* input count */ + 1 /* output count */ + 4 /* locktime */ ;
498
+ let total_output_size: u64 = must_pay_to
499
+ . iter ( )
500
+ . map (
501
+ |output| 8 /* value */ + 1 /* script len */ + output. script_pubkey . len ( ) as u64 ,
502
+ )
503
+ . sum ( ) ;
504
+ let total_satisfaction_weight: u64 =
505
+ must_spend. iter ( ) . map ( |input| input. satisfaction_weight ) . sum ( ) ;
506
+ let total_input_weight =
507
+ ( BASE_INPUT_WEIGHT * must_spend. len ( ) as u64 ) + total_satisfaction_weight;
508
+
509
+ let preexisting_tx_weight = 2 /* segwit marker & flag */ + total_input_weight +
510
+ ( ( BASE_TX_SIZE + total_output_size) * WITNESS_SCALE_FACTOR as u64 ) ;
511
+ let input_amount_sat = must_spend. iter ( ) . map ( |input| input. previous_utxo . value ) . sum ( ) ;
512
+ let target_amount_sat = must_pay_to. iter ( ) . map ( |output| output. value ) . sum ( ) ;
513
+ let do_coin_selection =
514
+ |force_conflicting_utxo_spend : bool , tolerate_high_network_feerates : bool | {
515
+ log_debug ! ( self . logger, "Attempting coin selection targeting {} sat/kW (force_conflicting_utxo_spend = {}, tolerate_high_network_feerates = {})" ,
516
+ target_feerate_sat_per_1000_weight, force_conflicting_utxo_spend, tolerate_high_network_feerates) ;
517
+ self . select_confirmed_utxos_internal (
518
+ & utxos,
519
+ claim_id,
520
+ force_conflicting_utxo_spend,
521
+ tolerate_high_network_feerates,
522
+ target_feerate_sat_per_1000_weight,
523
+ preexisting_tx_weight,
524
+ input_amount_sat,
525
+ target_amount_sat,
526
+ )
527
+ } ;
528
+ do_coin_selection ( false , false )
529
+ . or_else ( |_| do_coin_selection ( false , true ) )
530
+ . or_else ( |_| do_coin_selection ( true , false ) )
531
+ . or_else ( |_| do_coin_selection ( true , true ) )
532
+ } )
519
533
}
520
534
521
535
fn sign_psbt ( & self , psbt : Psbt ) -> Result < Transaction , ( ) > {
@@ -630,8 +644,11 @@ where
630
644
log_debug ! ( self . logger, "Performing coin selection for commitment package (commitment and anchor transaction) targeting {} sat/kW" ,
631
645
package_target_feerate_sat_per_1000_weight) ;
632
646
let coin_selection: CoinSelection = self . utxo_source . select_confirmed_utxos (
633
- claim_id, must_spend, & [ ] , package_target_feerate_sat_per_1000_weight,
634
- ) ?;
647
+ claim_id,
648
+ must_spend,
649
+ & [ ] ,
650
+ package_target_feerate_sat_per_1000_weight,
651
+ ) . await ?;
635
652
636
653
let mut anchor_tx = Transaction {
637
654
version : Version :: TWO ,
@@ -752,8 +769,11 @@ where
752
769
let must_spend_amount = must_spend. iter ( ) . map ( |input| input. previous_utxo . value . to_sat ( ) ) . sum :: < u64 > ( ) ;
753
770
754
771
let coin_selection: CoinSelection = self . utxo_source . select_confirmed_utxos (
755
- claim_id, must_spend, & htlc_tx. output , target_feerate_sat_per_1000_weight,
756
- ) ?;
772
+ claim_id,
773
+ must_spend,
774
+ & htlc_tx. output ,
775
+ target_feerate_sat_per_1000_weight,
776
+ ) . await ?;
757
777
758
778
#[ cfg( debug_assertions) ]
759
779
let total_satisfaction_weight = must_spend_satisfaction_weight +
@@ -828,11 +848,17 @@ where
828
848
log_info ! ( self . logger, "Handling channel close bump (claim_id = {}, commitment_txid = {})" ,
829
849
log_bytes!( claim_id. 0 ) , commitment_tx. compute_txid( ) ) ;
830
850
if let Err ( _) = self . handle_channel_close (
831
- * claim_id, * package_target_feerate_sat_per_1000_weight, commitment_tx,
832
- * commitment_tx_fee_satoshis, anchor_descriptor,
851
+ * claim_id,
852
+ * package_target_feerate_sat_per_1000_weight,
853
+ commitment_tx,
854
+ * commitment_tx_fee_satoshis,
855
+ anchor_descriptor,
833
856
) . await {
834
- log_error ! ( self . logger, "Failed bumping commitment transaction fee for {}" ,
835
- commitment_tx. compute_txid( ) ) ;
857
+ log_error ! (
858
+ self . logger,
859
+ "Failed bumping commitment transaction fee for {}" ,
860
+ commitment_tx. compute_txid( )
861
+ ) ;
836
862
}
837
863
}
838
864
BumpTransactionEvent :: HTLCResolution {
@@ -841,10 +867,16 @@ where
841
867
log_info ! ( self . logger, "Handling HTLC bump (claim_id = {}, htlcs_to_claim = {})" ,
842
868
log_bytes!( claim_id. 0 ) , log_iter!( htlc_descriptors. iter( ) . map( |d| d. outpoint( ) ) ) ) ;
843
869
if let Err ( _) = self . handle_htlc_resolution (
844
- * claim_id, * target_feerate_sat_per_1000_weight, htlc_descriptors, * tx_lock_time,
870
+ * claim_id,
871
+ * target_feerate_sat_per_1000_weight,
872
+ htlc_descriptors,
873
+ * tx_lock_time,
845
874
) . await {
846
- log_error ! ( self . logger, "Failed bumping HTLC transaction fee for commitment {}" ,
847
- htlc_descriptors[ 0 ] . commitment_txid) ;
875
+ log_error ! (
876
+ self . logger,
877
+ "Failed bumping HTLC transaction fee for commitment {}" ,
878
+ htlc_descriptors[ 0 ] . commitment_txid
879
+ ) ;
848
880
}
849
881
}
850
882
}
@@ -871,20 +903,19 @@ mod tests {
871
903
expected_selects : Mutex < Vec < ( u64 , u64 , u32 , CoinSelection ) > > ,
872
904
}
873
905
impl CoinSelectionSource for TestCoinSelectionSource {
874
- fn select_confirmed_utxos (
875
- & self ,
876
- _claim_id : ClaimId ,
877
- must_spend : Vec < Input > ,
878
- _must_pay_to : & [ TxOut ] ,
879
- target_feerate_sat_per_1000_weight : u32
880
- ) -> Result < CoinSelection , ( ) > {
906
+ fn select_confirmed_utxos < ' a > (
907
+ & ' a self , _claim_id : ClaimId , must_spend : Vec < Input > , _must_pay_to : & ' a [ TxOut ] ,
908
+ target_feerate_sat_per_1000_weight : u32 ,
909
+ ) -> AsyncResult < ' a , CoinSelection > {
881
910
let mut expected_selects = self . expected_selects . lock ( ) . unwrap ( ) ;
882
911
let ( weight, value, feerate, res) = expected_selects. remove ( 0 ) ;
883
912
assert_eq ! ( must_spend. len( ) , 1 ) ;
884
913
assert_eq ! ( must_spend[ 0 ] . satisfaction_weight, weight) ;
885
914
assert_eq ! ( must_spend[ 0 ] . previous_utxo. value. to_sat( ) , value) ;
886
915
assert_eq ! ( target_feerate_sat_per_1000_weight, feerate) ;
887
- Ok ( res)
916
+ Box :: pin ( async move {
917
+ Ok ( res)
918
+ } )
888
919
}
889
920
fn sign_psbt ( & self , psbt : Psbt ) -> Result < Transaction , ( ) > {
890
921
let mut tx = psbt. unsigned_tx ;
0 commit comments