12
12
//! [`Event`]: crate::events::Event
13
13
14
14
use alloc:: collections:: BTreeMap ;
15
+ use core:: future:: Future ;
15
16
use core:: ops:: Deref ;
17
+ use core:: task;
16
18
17
19
use crate :: chain:: chaininterface:: { fee_for_weight, BroadcasterInterface } ;
18
20
use crate :: chain:: ClaimId ;
@@ -29,8 +31,9 @@ use crate::sign::ecdsa::EcdsaChannelSigner;
29
31
use crate :: sign:: {
30
32
ChannelDerivationParameters , HTLCDescriptor , SignerProvider , P2WPKH_WITNESS_WEIGHT ,
31
33
} ;
34
+ use crate :: sync:: Arc ;
32
35
use crate :: sync:: Mutex ;
33
- use crate :: util:: async_poll:: { AsyncResult , MaybeSend , MaybeSync } ;
36
+ use crate :: util:: async_poll:: { dummy_waker , AsyncResult , MaybeSend , MaybeSync } ;
34
37
use crate :: util:: logger:: Logger ;
35
38
36
39
use bitcoin:: amount:: Amount ;
@@ -359,6 +362,63 @@ pub trait CoinSelectionSource {
359
362
fn sign_psbt < ' a > ( & ' a self , psbt : Psbt ) -> AsyncResult < ' a , Transaction > ;
360
363
}
361
364
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
+
362
422
/// An alternative to [`CoinSelectionSource`] that can be implemented and used along [`Wallet`] to
363
423
/// provide a default implementation to [`CoinSelectionSource`].
364
424
pub trait WalletSource {
@@ -1045,6 +1105,51 @@ where
1045
1105
}
1046
1106
}
1047
1107
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
+
1048
1153
#[ cfg( test) ]
1049
1154
mod tests {
1050
1155
use super :: * ;
0 commit comments