@@ -30,7 +30,7 @@ use crate::sign::{
3030} ;
3131use crate :: sign:: ecdsa:: EcdsaChannelSigner ;
3232use crate :: sync:: Mutex ;
33- use crate :: util:: async_poll:: AsyncResult ;
33+ use crate :: util:: async_poll:: { AsyncResult , MaybeSync } ;
3434use crate :: util:: logger:: Logger ;
3535
3636use bitcoin:: { OutPoint , Psbt , PubkeyHash , Sequence , ScriptBuf , Transaction , TxIn , TxOut , Witness , WPubkeyHash } ;
@@ -345,10 +345,10 @@ pub trait CoinSelectionSource {
345345 /// other claims, implementations must be willing to double spend their UTXOs. The choice of
346346 /// which UTXOs to double spend is left to the implementation, but it must strive to keep the
347347 /// 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 ] ,
350350 target_feerate_sat_per_1000_weight : u32 ,
351- ) -> Result < CoinSelection , ( ) > ;
351+ ) -> AsyncResult < ' a , CoinSelection > ;
352352 /// Signs and provides the full witness for all inputs within the transaction known to the
353353 /// trait (i.e., any provided via [`CoinSelectionSource::select_confirmed_utxos`]).
354354 ///
@@ -361,7 +361,7 @@ pub trait CoinSelectionSource {
361361/// provide a default implementation to [`CoinSelectionSource`].
362362pub trait WalletSource {
363363 /// 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 > > ;
365365 /// Returns a script to use for change above dust resulting from a successful coin selection
366366 /// attempt.
367367 fn get_change_script ( & self ) -> Result < ScriptBuf , ( ) > ;
@@ -482,40 +482,54 @@ where
482482 }
483483}
484484
485- impl < W : Deref , L : Deref > CoinSelectionSource for Wallet < W , L >
485+ impl < W : Deref + MaybeSync , L : Deref + MaybeSync > CoinSelectionSource for Wallet < W , L >
486486where
487487 W :: Target : WalletSource ,
488- L :: Target : Logger
488+ L :: Target : Logger ,
489489{
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 ] ,
492492 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+ } )
519533 }
520534
521535 fn sign_psbt ( & self , psbt : Psbt ) -> Result < Transaction , ( ) > {
@@ -630,8 +644,11 @@ where
630644 log_debug ! ( self . logger, "Performing coin selection for commitment package (commitment and anchor transaction) targeting {} sat/kW" ,
631645 package_target_feerate_sat_per_1000_weight) ;
632646 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 ?;
635652
636653 let mut anchor_tx = Transaction {
637654 version : Version :: TWO ,
@@ -752,8 +769,11 @@ where
752769 let must_spend_amount = must_spend. iter ( ) . map ( |input| input. previous_utxo . value . to_sat ( ) ) . sum :: < u64 > ( ) ;
753770
754771 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 ?;
757777
758778 #[ cfg( debug_assertions) ]
759779 let total_satisfaction_weight = must_spend_satisfaction_weight +
@@ -828,11 +848,17 @@ where
828848 log_info ! ( self . logger, "Handling channel close bump (claim_id = {}, commitment_txid = {})" ,
829849 log_bytes!( claim_id. 0 ) , commitment_tx. compute_txid( ) ) ;
830850 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,
833856 ) . 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+ ) ;
836862 }
837863 }
838864 BumpTransactionEvent :: HTLCResolution {
@@ -841,10 +867,16 @@ where
841867 log_info ! ( self . logger, "Handling HTLC bump (claim_id = {}, htlcs_to_claim = {})" ,
842868 log_bytes!( claim_id. 0 ) , log_iter!( htlc_descriptors. iter( ) . map( |d| d. outpoint( ) ) ) ) ;
843869 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,
845874 ) . 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+ ) ;
848880 }
849881 }
850882 }
@@ -871,20 +903,19 @@ mod tests {
871903 expected_selects : Mutex < Vec < ( u64 , u64 , u32 , CoinSelection ) > > ,
872904 }
873905 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 > {
881910 let mut expected_selects = self . expected_selects . lock ( ) . unwrap ( ) ;
882911 let ( weight, value, feerate, res) = expected_selects. remove ( 0 ) ;
883912 assert_eq ! ( must_spend. len( ) , 1 ) ;
884913 assert_eq ! ( must_spend[ 0 ] . satisfaction_weight, weight) ;
885914 assert_eq ! ( must_spend[ 0 ] . previous_utxo. value. to_sat( ) , value) ;
886915 assert_eq ! ( target_feerate_sat_per_1000_weight, feerate) ;
887- Ok ( res)
916+ Box :: pin ( async move {
917+ Ok ( res)
918+ } )
888919 }
889920 fn sign_psbt ( & self , psbt : Psbt ) -> Result < Transaction , ( ) > {
890921 let mut tx = psbt. unsigned_tx ;
0 commit comments