@@ -26,7 +26,7 @@ use crate::ln::chan_utils::{
26
26
} ;
27
27
use crate :: prelude:: * ;
28
28
use crate :: sign:: {
29
- ChannelDerivationParameters , HTLCDescriptor , SignerProvider , P2WPKH_WITNESS_WEIGHT
29
+ AsyncResult , ChannelDerivationParameters , HTLCDescriptor , SignerProvider , P2WPKH_WITNESS_WEIGHT
30
30
} ;
31
31
use crate :: sign:: ecdsa:: EcdsaChannelSigner ;
32
32
use crate :: sync:: Mutex ;
@@ -344,10 +344,10 @@ pub trait CoinSelectionSource {
344
344
/// other claims, implementations must be willing to double spend their UTXOs. The choice of
345
345
/// which UTXOs to double spend is left to the implementation, but it must strive to keep the
346
346
/// 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 ] ,
349
349
target_feerate_sat_per_1000_weight : u32 ,
350
- ) -> Result < CoinSelection , ( ) > ;
350
+ ) -> AsyncResult < ' a , CoinSelection > ;
351
351
/// Signs and provides the full witness for all inputs within the transaction known to the
352
352
/// trait (i.e., any provided via [`CoinSelectionSource::select_confirmed_utxos`]).
353
353
///
@@ -360,7 +360,7 @@ pub trait CoinSelectionSource {
360
360
/// provide a default implementation to [`CoinSelectionSource`].
361
361
pub trait WalletSource {
362
362
/// 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 > > ;
364
364
/// Returns a script to use for change above dust resulting from a successful coin selection
365
365
/// attempt.
366
366
fn get_change_script ( & self ) -> Result < ScriptBuf , ( ) > ;
@@ -481,40 +481,54 @@ where
481
481
}
482
482
}
483
483
484
- impl < W : Deref , L : Deref > CoinSelectionSource for Wallet < W , L >
484
+ impl < W : Deref + Sync , L : Deref + Sync > CoinSelectionSource for Wallet < W , L >
485
485
where
486
486
W :: Target : WalletSource ,
487
- L :: Target : Logger
487
+ L :: Target : Logger ,
488
488
{
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 ] ,
491
491
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
+ } )
518
532
}
519
533
520
534
fn sign_psbt ( & self , psbt : Psbt ) -> Result < Transaction , ( ) > {
@@ -629,8 +643,11 @@ where
629
643
log_debug ! ( self . logger, "Performing coin selection for commitment package (commitment and anchor transaction) targeting {} sat/kW" ,
630
644
package_target_feerate_sat_per_1000_weight) ;
631
645
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 ?;
634
651
635
652
let mut anchor_tx = Transaction {
636
653
version : Version :: TWO ,
@@ -751,8 +768,11 @@ where
751
768
let must_spend_amount = must_spend. iter ( ) . map ( |input| input. previous_utxo . value . to_sat ( ) ) . sum :: < u64 > ( ) ;
752
769
753
770
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 ?;
756
776
757
777
#[ cfg( debug_assertions) ]
758
778
let total_satisfaction_weight = must_spend_satisfaction_weight +
@@ -827,11 +847,17 @@ where
827
847
log_info ! ( self . logger, "Handling channel close bump (claim_id = {}, commitment_txid = {})" ,
828
848
log_bytes!( claim_id. 0 ) , commitment_tx. compute_txid( ) ) ;
829
849
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,
832
855
) . 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
+ ) ;
835
861
}
836
862
}
837
863
BumpTransactionEvent :: HTLCResolution {
@@ -840,10 +866,16 @@ where
840
866
log_info ! ( self . logger, "Handling HTLC bump (claim_id = {}, htlcs_to_claim = {})" ,
841
867
log_bytes!( claim_id. 0 ) , log_iter!( htlc_descriptors. iter( ) . map( |d| d. outpoint( ) ) ) ) ;
842
868
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,
844
873
) . 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
+ ) ;
847
879
}
848
880
}
849
881
}
@@ -870,20 +902,19 @@ mod tests {
870
902
expected_selects : Mutex < Vec < ( u64 , u64 , u32 , CoinSelection ) > > ,
871
903
}
872
904
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 > {
880
909
let mut expected_selects = self . expected_selects . lock ( ) . unwrap ( ) ;
881
910
let ( weight, value, feerate, res) = expected_selects. remove ( 0 ) ;
882
911
assert_eq ! ( must_spend. len( ) , 1 ) ;
883
912
assert_eq ! ( must_spend[ 0 ] . satisfaction_weight, weight) ;
884
913
assert_eq ! ( must_spend[ 0 ] . previous_utxo. value. to_sat( ) , value) ;
885
914
assert_eq ! ( target_feerate_sat_per_1000_weight, feerate) ;
886
- Ok ( res)
915
+ Box :: pin ( async move {
916
+ Ok ( res)
917
+ } )
887
918
}
888
919
fn sign_psbt ( & self , psbt : Psbt ) -> Result < Transaction , ( ) > {
889
920
let mut tx = psbt. unsigned_tx ;
0 commit comments