@@ -26,7 +26,7 @@ use crate::ln::chan_utils::{
2626} ;
2727use crate :: prelude:: * ;
2828use crate :: sign:: {
29- ChannelDerivationParameters , HTLCDescriptor , SignerProvider , P2WPKH_WITNESS_WEIGHT
29+ AsyncResult , ChannelDerivationParameters , HTLCDescriptor , SignerProvider , P2WPKH_WITNESS_WEIGHT
3030} ;
3131use crate :: sign:: ecdsa:: EcdsaChannelSigner ;
3232use crate :: sync:: Mutex ;
@@ -344,10 +344,10 @@ pub trait CoinSelectionSource {
344344 /// other claims, implementations must be willing to double spend their UTXOs. The choice of
345345 /// which UTXOs to double spend is left to the implementation, but it must strive to keep the
346346 /// set of other claims being double spent to a minimum.
347- fn select_confirmed_utxos (
348- & self , claim_id : ClaimId , must_spend : Vec < Input > , must_pay_to : & [ TxOut ] ,
347+ fn select_confirmed_utxos < ' a > (
348+ & ' a self , claim_id : ClaimId , must_spend : Vec < Input > , must_pay_to : & ' a [ TxOut ] ,
349349 target_feerate_sat_per_1000_weight : u32 ,
350- ) -> Result < CoinSelection , ( ) > ;
350+ ) -> AsyncResult < ' a , CoinSelection > ;
351351 /// Signs and provides the full witness for all inputs within the transaction known to the
352352 /// trait (i.e., any provided via [`CoinSelectionSource::select_confirmed_utxos`]).
353353 ///
@@ -360,7 +360,7 @@ pub trait CoinSelectionSource {
360360/// provide a default implementation to [`CoinSelectionSource`].
361361pub trait WalletSource {
362362 /// Returns all UTXOs, with at least 1 confirmation each, that are available to spend.
363- fn list_confirmed_utxos ( & self ) -> Result < Vec < Utxo > , ( ) > ;
363+ fn list_confirmed_utxos < ' a > ( & ' a self ) -> AsyncResult < ' a , Vec < Utxo > > ;
364364 /// Returns a script to use for change above dust resulting from a successful coin selection
365365 /// attempt.
366366 fn get_change_script ( & self ) -> Result < ScriptBuf , ( ) > ;
@@ -481,40 +481,54 @@ where
481481 }
482482}
483483
484- impl < W : Deref , L : Deref > CoinSelectionSource for Wallet < W , L >
484+ impl < W : Deref + Sync , L : Deref + Sync > CoinSelectionSource for Wallet < W , L >
485485where
486486 W :: Target : WalletSource ,
487- L :: Target : Logger
487+ L :: Target : Logger ,
488488{
489- fn select_confirmed_utxos (
490- & self , claim_id : ClaimId , must_spend : Vec < Input > , must_pay_to : & [ TxOut ] ,
489+ fn select_confirmed_utxos < ' a > (
490+ & ' a self , claim_id : ClaimId , must_spend : Vec < Input > , must_pay_to : & ' a [ TxOut ] ,
491491 target_feerate_sat_per_1000_weight : u32 ,
492- ) -> Result < CoinSelection , ( ) > {
493- let utxos = self . source . list_confirmed_utxos ( ) ?;
494- // TODO: Use fee estimation utils when we upgrade to bitcoin v0.30.0.
495- const BASE_TX_SIZE : u64 = 4 /* version */ + 1 /* input count */ + 1 /* output count */ + 4 /* locktime */ ;
496- let total_output_size: u64 = must_pay_to. iter ( ) . map ( |output|
497- 8 /* value */ + 1 /* script len */ + output. script_pubkey . len ( ) as u64
498- ) . sum ( ) ;
499- let total_satisfaction_weight: u64 = must_spend. iter ( ) . map ( |input| input. satisfaction_weight ) . sum ( ) ;
500- let total_input_weight = ( BASE_INPUT_WEIGHT * must_spend. len ( ) as u64 ) + total_satisfaction_weight;
501-
502- let preexisting_tx_weight = 2 /* segwit marker & flag */ + total_input_weight +
503- ( ( BASE_TX_SIZE + total_output_size) * WITNESS_SCALE_FACTOR as u64 ) ;
504- let input_amount_sat = must_spend. iter ( ) . map ( |input| input. previous_utxo . value ) . sum ( ) ;
505- let target_amount_sat = must_pay_to. iter ( ) . map ( |output| output. value ) . sum ( ) ;
506- let do_coin_selection = |force_conflicting_utxo_spend : bool , tolerate_high_network_feerates : bool | {
507- log_debug ! ( self . logger, "Attempting coin selection targeting {} sat/kW (force_conflicting_utxo_spend = {}, tolerate_high_network_feerates = {})" ,
508- target_feerate_sat_per_1000_weight, force_conflicting_utxo_spend, tolerate_high_network_feerates) ;
509- self . select_confirmed_utxos_internal (
510- & utxos, claim_id, force_conflicting_utxo_spend, tolerate_high_network_feerates,
511- target_feerate_sat_per_1000_weight, preexisting_tx_weight, input_amount_sat, target_amount_sat,
512- )
513- } ;
514- do_coin_selection ( false , false )
515- . or_else ( |_| do_coin_selection ( false , true ) )
516- . or_else ( |_| do_coin_selection ( true , false ) )
517- . or_else ( |_| do_coin_selection ( true , true ) )
492+ ) -> AsyncResult < ' a , CoinSelection > {
493+ Box :: pin ( async move {
494+ let utxos = self . source . list_confirmed_utxos ( ) . await ?;
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
498+ . iter ( )
499+ . map (
500+ |output| 8 /* value */ + 1 /* script len */ + output. script_pubkey . len ( ) as u64 ,
501+ )
502+ . sum ( ) ;
503+ let total_satisfaction_weight: u64 =
504+ must_spend. iter ( ) . map ( |input| input. satisfaction_weight ) . sum ( ) ;
505+ let total_input_weight =
506+ ( BASE_INPUT_WEIGHT * must_spend. len ( ) as u64 ) + total_satisfaction_weight;
507+
508+ let preexisting_tx_weight = 2 /* segwit marker & flag */ + total_input_weight +
509+ ( ( BASE_TX_SIZE + total_output_size) * WITNESS_SCALE_FACTOR as u64 ) ;
510+ let input_amount_sat = must_spend. iter ( ) . map ( |input| input. previous_utxo . value ) . sum ( ) ;
511+ let target_amount_sat = must_pay_to. iter ( ) . map ( |output| output. value ) . sum ( ) ;
512+ let do_coin_selection =
513+ |force_conflicting_utxo_spend : bool , tolerate_high_network_feerates : bool | {
514+ log_debug ! ( self . logger, "Attempting coin selection targeting {} sat/kW (force_conflicting_utxo_spend = {}, tolerate_high_network_feerates = {})" ,
515+ target_feerate_sat_per_1000_weight, force_conflicting_utxo_spend, tolerate_high_network_feerates) ;
516+ self . select_confirmed_utxos_internal (
517+ & utxos,
518+ claim_id,
519+ force_conflicting_utxo_spend,
520+ tolerate_high_network_feerates,
521+ target_feerate_sat_per_1000_weight,
522+ preexisting_tx_weight,
523+ input_amount_sat,
524+ target_amount_sat,
525+ )
526+ } ;
527+ do_coin_selection ( false , false )
528+ . or_else ( |_| do_coin_selection ( false , true ) )
529+ . or_else ( |_| do_coin_selection ( true , false ) )
530+ . or_else ( |_| do_coin_selection ( true , true ) )
531+ } )
518532 }
519533
520534 fn sign_psbt ( & self , psbt : Psbt ) -> Result < Transaction , ( ) > {
@@ -629,8 +643,11 @@ where
629643 log_debug ! ( self . logger, "Performing coin selection for commitment package (commitment and anchor transaction) targeting {} sat/kW" ,
630644 package_target_feerate_sat_per_1000_weight) ;
631645 let coin_selection: CoinSelection = self . utxo_source . select_confirmed_utxos (
632- claim_id, must_spend, & [ ] , package_target_feerate_sat_per_1000_weight,
633- ) ?;
646+ claim_id,
647+ must_spend,
648+ & [ ] ,
649+ package_target_feerate_sat_per_1000_weight,
650+ ) . await ?;
634651
635652 let mut anchor_tx = Transaction {
636653 version : Version :: TWO ,
@@ -751,8 +768,11 @@ where
751768 let must_spend_amount = must_spend. iter ( ) . map ( |input| input. previous_utxo . value . to_sat ( ) ) . sum :: < u64 > ( ) ;
752769
753770 let coin_selection: CoinSelection = self . utxo_source . select_confirmed_utxos (
754- claim_id, must_spend, & htlc_tx. output , target_feerate_sat_per_1000_weight,
755- ) ?;
771+ claim_id,
772+ must_spend,
773+ & htlc_tx. output ,
774+ target_feerate_sat_per_1000_weight,
775+ ) . await ?;
756776
757777 #[ cfg( debug_assertions) ]
758778 let total_satisfaction_weight = must_spend_satisfaction_weight +
@@ -827,11 +847,17 @@ where
827847 log_info ! ( self . logger, "Handling channel close bump (claim_id = {}, commitment_txid = {})" ,
828848 log_bytes!( claim_id. 0 ) , commitment_tx. compute_txid( ) ) ;
829849 if let Err ( _) = self . handle_channel_close (
830- * claim_id, * package_target_feerate_sat_per_1000_weight, commitment_tx,
831- * commitment_tx_fee_satoshis, anchor_descriptor,
850+ * claim_id,
851+ * package_target_feerate_sat_per_1000_weight,
852+ commitment_tx,
853+ * commitment_tx_fee_satoshis,
854+ anchor_descriptor,
832855 ) . await {
833- log_error ! ( self . logger, "Failed bumping commitment transaction fee for {}" ,
834- commitment_tx. compute_txid( ) ) ;
856+ log_error ! (
857+ self . logger,
858+ "Failed bumping commitment transaction fee for {}" ,
859+ commitment_tx. compute_txid( )
860+ ) ;
835861 }
836862 }
837863 BumpTransactionEvent :: HTLCResolution {
@@ -840,10 +866,16 @@ where
840866 log_info ! ( self . logger, "Handling HTLC bump (claim_id = {}, htlcs_to_claim = {})" ,
841867 log_bytes!( claim_id. 0 ) , log_iter!( htlc_descriptors. iter( ) . map( |d| d. outpoint( ) ) ) ) ;
842868 if let Err ( _) = self . handle_htlc_resolution (
843- * claim_id, * target_feerate_sat_per_1000_weight, htlc_descriptors, * tx_lock_time,
869+ * claim_id,
870+ * target_feerate_sat_per_1000_weight,
871+ htlc_descriptors,
872+ * tx_lock_time,
844873 ) . await {
845- log_error ! ( self . logger, "Failed bumping HTLC transaction fee for commitment {}" ,
846- htlc_descriptors[ 0 ] . commitment_txid) ;
874+ log_error ! (
875+ self . logger,
876+ "Failed bumping HTLC transaction fee for commitment {}" ,
877+ htlc_descriptors[ 0 ] . commitment_txid
878+ ) ;
847879 }
848880 }
849881 }
@@ -870,20 +902,19 @@ mod tests {
870902 expected_selects : Mutex < Vec < ( u64 , u64 , u32 , CoinSelection ) > > ,
871903 }
872904 impl CoinSelectionSource for TestCoinSelectionSource {
873- fn select_confirmed_utxos (
874- & self ,
875- _claim_id : ClaimId ,
876- must_spend : Vec < Input > ,
877- _must_pay_to : & [ TxOut ] ,
878- target_feerate_sat_per_1000_weight : u32
879- ) -> Result < CoinSelection , ( ) > {
905+ fn select_confirmed_utxos < ' a > (
906+ & ' a self , _claim_id : ClaimId , must_spend : Vec < Input > , _must_pay_to : & ' a [ TxOut ] ,
907+ target_feerate_sat_per_1000_weight : u32 ,
908+ ) -> AsyncResult < ' a , CoinSelection > {
880909 let mut expected_selects = self . expected_selects . lock ( ) . unwrap ( ) ;
881910 let ( weight, value, feerate, res) = expected_selects. remove ( 0 ) ;
882911 assert_eq ! ( must_spend. len( ) , 1 ) ;
883912 assert_eq ! ( must_spend[ 0 ] . satisfaction_weight, weight) ;
884913 assert_eq ! ( must_spend[ 0 ] . previous_utxo. value. to_sat( ) , value) ;
885914 assert_eq ! ( target_feerate_sat_per_1000_weight, feerate) ;
886- Ok ( res)
915+ Box :: pin ( async move {
916+ Ok ( res)
917+ } )
887918 }
888919 fn sign_psbt ( & self , psbt : Psbt ) -> Result < Transaction , ( ) > {
889920 let mut tx = psbt. unsigned_tx ;
0 commit comments