1212//! [`Event`]: crate::events::Event
1313
1414use alloc:: collections:: BTreeMap ;
15+ use core:: future:: Future ;
1516use core:: ops:: Deref ;
17+ use core:: task;
1618
1719use crate :: chain:: chaininterface:: { fee_for_weight, BroadcasterInterface } ;
1820use crate :: chain:: ClaimId ;
@@ -29,8 +31,9 @@ use crate::sign::ecdsa::EcdsaChannelSigner;
2931use crate :: sign:: {
3032 ChannelDerivationParameters , HTLCDescriptor , SignerProvider , P2WPKH_WITNESS_WEIGHT ,
3133} ;
34+ use crate :: sync:: Arc ;
3235use crate :: sync:: Mutex ;
33- use crate :: util:: async_poll:: { AsyncResult , MaybeSend , MaybeSync } ;
36+ use crate :: util:: async_poll:: { dummy_waker , AsyncResult , MaybeSend , MaybeSync } ;
3437use crate :: util:: logger:: Logger ;
3538
3639use bitcoin:: amount:: Amount ;
@@ -359,6 +362,63 @@ pub trait CoinSelectionSource {
359362 fn sign_psbt < ' a > ( & ' a self , psbt : Psbt ) -> AsyncResult < ' a , Transaction > ;
360363}
361364
365+ /// A synchronous helper trait that can be used to implement [`CoinSelectionSource`] in a synchronous
366+ /// context.
367+ pub trait CoinSelectionSourceSync {
368+ /// A synchronous version of [`CoinSelectionSource::select_confirmed_utxos`].
369+ fn select_confirmed_utxos (
370+ & self , claim_id : ClaimId , must_spend : Vec < Input > , must_pay_to : & [ TxOut ] ,
371+ target_feerate_sat_per_1000_weight : u32 ,
372+ ) -> Result < CoinSelection , ( ) > ;
373+
374+ /// A synchronous version of [`CoinSelectionSource::sign_psbt`].
375+ fn sign_psbt ( & self , psbt : Psbt ) -> Result < Transaction , ( ) > ;
376+ }
377+
378+ /// A wrapper around [`CoinSelectionSourceSync`] to allow for async calls. This wrapper isn't intended to be used
379+ /// directly, because that would risk blocking an async context.
380+ #[ cfg( any( test, feature = "_test_utils" ) ) ]
381+ pub struct CoinSelectionSourceSyncWrapper < T : Deref > ( T )
382+ where
383+ T :: Target : CoinSelectionSourceSync ;
384+ #[ cfg( not( any( test, feature = "_test_utils" ) ) ) ]
385+ pub ( crate ) struct CoinSelectionSourceSyncWrapper < T : Deref > ( T )
386+ where
387+ T :: Target : CoinSelectionSourceSync ;
388+
389+ impl < T : Deref > CoinSelectionSourceSyncWrapper < T >
390+ where
391+ T :: Target : CoinSelectionSourceSync ,
392+ {
393+ #[ allow( dead_code) ]
394+ pub fn new ( source : T ) -> Self {
395+ Self ( source)
396+ }
397+ }
398+
399+ impl < T : Deref > CoinSelectionSource for CoinSelectionSourceSyncWrapper < T >
400+ where
401+ T :: Target : CoinSelectionSourceSync ,
402+ {
403+ fn select_confirmed_utxos < ' a > (
404+ & ' a self , claim_id : ClaimId , must_spend : Vec < Input > , must_pay_to : & ' a [ TxOut ] ,
405+ target_feerate_sat_per_1000_weight : u32 ,
406+ ) -> AsyncResult < ' a , CoinSelection > {
407+ let coins = self . 0 . select_confirmed_utxos (
408+ claim_id,
409+ must_spend,
410+ must_pay_to,
411+ target_feerate_sat_per_1000_weight,
412+ ) ;
413+ Box :: pin ( async move { coins } )
414+ }
415+
416+ fn sign_psbt < ' a > ( & ' a self , psbt : Psbt ) -> AsyncResult < ' a , Transaction > {
417+ let psbt = self . 0 . sign_psbt ( psbt) ;
418+ Box :: pin ( async move { psbt } )
419+ }
420+ }
421+
362422/// An alternative to [`CoinSelectionSource`] that can be implemented and used along [`Wallet`] to
363423/// provide a default implementation to [`CoinSelectionSource`].
364424pub trait WalletSource {
@@ -1045,6 +1105,51 @@ where
10451105 }
10461106}
10471107
1108+ /// A synchronous wrapper around [`BumpTransactionEventHandler`] to be used in contexts where async is not available.
1109+ pub struct BumpTransactionEventHandlerSync < B : Deref , C : Deref , SP : Deref , L : Deref >
1110+ where
1111+ B :: Target : BroadcasterInterface ,
1112+ C :: Target : CoinSelectionSourceSync ,
1113+ SP :: Target : SignerProvider ,
1114+ L :: Target : Logger ,
1115+ {
1116+ bump_transaction_event_handler :
1117+ Arc < BumpTransactionEventHandler < B , Arc < CoinSelectionSourceSyncWrapper < C > > , SP , L > > ,
1118+ }
1119+
1120+ impl < B : Deref , C : Deref , SP : Deref , L : Deref > BumpTransactionEventHandlerSync < B , C , SP , L >
1121+ where
1122+ B :: Target : BroadcasterInterface ,
1123+ C :: Target : CoinSelectionSourceSync ,
1124+ SP :: Target : SignerProvider ,
1125+ L :: Target : Logger ,
1126+ {
1127+ /// Constructs a new instance of [`BumpTransactionEventHandlerSync`].
1128+ pub fn new ( broadcaster : B , utxo_source : C , signer_provider : SP , logger : L ) -> Self {
1129+ let bump_transaction_event_handler = Arc :: new ( BumpTransactionEventHandler :: new (
1130+ broadcaster,
1131+ Arc :: new ( CoinSelectionSourceSyncWrapper ( utxo_source) ) ,
1132+ signer_provider,
1133+ logger,
1134+ ) ) ;
1135+ Self { bump_transaction_event_handler }
1136+ }
1137+
1138+ /// Handles all variants of [`BumpTransactionEvent`].
1139+ pub fn handle_event ( & self , event : & BumpTransactionEvent ) {
1140+ let mut fut = Box :: pin ( self . bump_transaction_event_handler . handle_event ( event) ) ;
1141+ let mut waker = dummy_waker ( ) ;
1142+ let mut ctx = task:: Context :: from_waker ( & mut waker) ;
1143+ match fut. as_mut ( ) . poll ( & mut ctx) {
1144+ task:: Poll :: Ready ( result) => result,
1145+ task:: Poll :: Pending => {
1146+ // In a sync context, we can't wait for the future to complete.
1147+ unreachable ! ( "BumpTransactionEventHandlerSync::handle_event should not be pending in a sync context" ) ;
1148+ } ,
1149+ }
1150+ }
1151+ }
1152+
10481153#[ cfg( test) ]
10491154mod tests {
10501155 use super :: * ;
0 commit comments