Skip to content

Commit 534ee90

Browse files
committed
f: add sync wrappers
1 parent 6641dd8 commit 534ee90

File tree

1 file changed

+106
-1
lines changed

1 file changed

+106
-1
lines changed

lightning/src/events/bump_transaction.rs

Lines changed: 106 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
//! [`Event`]: crate::events::Event
1313
1414
use alloc::collections::BTreeMap;
15+
use core::future::Future;
1516
use core::ops::Deref;
17+
use core::task;
1618

1719
use crate::chain::chaininterface::{fee_for_weight, BroadcasterInterface};
1820
use crate::chain::ClaimId;
@@ -29,8 +31,9 @@ use crate::sign::ecdsa::EcdsaChannelSigner;
2931
use crate::sign::{
3032
ChannelDerivationParameters, HTLCDescriptor, SignerProvider, P2WPKH_WITNESS_WEIGHT,
3133
};
34+
use crate::sync::Arc;
3235
use crate::sync::Mutex;
33-
use crate::util::async_poll::{AsyncResult, MaybeSend, MaybeSync};
36+
use crate::util::async_poll::{dummy_waker, AsyncResult, MaybeSend, MaybeSync};
3437
use crate::util::logger::Logger;
3538

3639
use 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`].
364424
pub 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)]
10491154
mod tests {
10501155
use super::*;

0 commit comments

Comments
 (0)