Skip to content

Commit 7357d81

Browse files
committed
Add async api
1 parent c407fe5 commit 7357d81

File tree

5 files changed

+307
-84
lines changed

5 files changed

+307
-84
lines changed

Diff for: lightning-background-processor/src/lib.rs

+21-14
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,18 @@ use lightning::onion_message::messenger::AOnionMessenger;
3636
use lightning::routing::gossip::{NetworkGraph, P2PGossipSync};
3737
use lightning::routing::scoring::{ScoreUpdate, WriteableScore};
3838
use lightning::routing::utxo::UtxoLookup;
39-
use lightning::sign::{ChangeDestinationSource, OutputSpender};
39+
#[cfg(feature = "futures")]
40+
use lightning::sign::ChangeDestinationSource;
41+
#[cfg(feature = "std")]
42+
use lightning::sign::ChangeDestinationSourceSync;
43+
use lightning::sign::OutputSpender;
4044
use lightning::util::logger::Logger;
4145
use lightning::util::persist::{KVStore, Persister};
46+
#[cfg(feature = "futures")]
4247
use lightning::util::sweep::OutputSweeper;
4348
#[cfg(feature = "std")]
49+
use lightning::util::sweep::OutputSweeperSync;
50+
#[cfg(feature = "std")]
4451
use lightning::util::wakers::Sleeper;
4552
use lightning_rapid_gossip_sync::RapidGossipSync;
4653

@@ -726,7 +733,7 @@ where
726733
gossip_sync,
727734
{
728735
if let Some(ref sweeper) = sweeper {
729-
sweeper.regenerate_and_broadcast_spend_if_necessary_locked()
736+
sweeper.regenerate_and_broadcast_spend_if_necessary().await
730737
} else {
731738
Ok(())
732739
}
@@ -843,16 +850,17 @@ impl BackgroundProcessor {
843850
PM: 'static + Deref + Send + Sync,
844851
S: 'static + Deref<Target = SC> + Send + Sync,
845852
SC: for<'b> WriteableScore<'b>,
846-
D: 'static + Deref + Send + Sync,
853+
D: Deref,
847854
O: 'static + Deref + Send + Sync,
848855
K: 'static + Deref + Send + Sync,
849-
OS: 'static + Deref<Target = OutputSweeper<T, D, F, CF, K, L, O>> + Send + Sync,
856+
OS: 'static + Deref<Target = OutputSweeperSync<T, D, F, CF, K, L, O>> + Send + Sync,
850857
>(
851858
persister: PS, event_handler: EH, chain_monitor: M, channel_manager: CM,
852859
onion_messenger: Option<OM>, gossip_sync: GossipSync<PGS, RGS, G, UL, L>, peer_manager: PM,
853860
sweeper: Option<OS>, logger: L, scorer: Option<S>,
854861
) -> Self
855862
where
863+
D::Target: ChangeDestinationSourceSync,
856864
UL::Target: 'static + UtxoLookup,
857865
CF::Target: 'static + chain::Filter + Sync + Send,
858866
T::Target: 'static + BroadcasterInterface,
@@ -864,7 +872,6 @@ impl BackgroundProcessor {
864872
OM::Target: AOnionMessenger + Send + Sync,
865873
PM::Target: APeerManager + Send + Sync,
866874
O::Target: 'static + OutputSpender + Send + Sync,
867-
D::Target: 'static + ChangeDestinationSource + Send + Sync,
868875
K::Target: 'static + KVStore + Send + Sync,
869876
{
870877
let stop_thread = Arc::new(AtomicBool::new(false));
@@ -903,7 +910,7 @@ impl BackgroundProcessor {
903910
gossip_sync,
904911
{
905912
if let Some(ref sweeper) = sweeper {
906-
sweeper.regenerate_and_broadcast_spend_if_necessary_locked()
913+
sweeper.regenerate_and_broadcast_spend_if_necessary()
907914
} else {
908915
Ok(())
909916
}
@@ -1020,7 +1027,7 @@ mod tests {
10201027
use lightning::routing::gossip::{NetworkGraph, P2PGossipSync};
10211028
use lightning::routing::router::{CandidateRouteHop, DefaultRouter, Path, RouteHop};
10221029
use lightning::routing::scoring::{ChannelUsage, LockableScore, ScoreLookUp, ScoreUpdate};
1023-
use lightning::sign::{ChangeDestinationSource, InMemorySigner, KeysManager};
1030+
use lightning::sign::{ChangeDestinationSourceSync, InMemorySigner, KeysManager};
10241031
use lightning::types::features::{ChannelFeatures, NodeFeatures};
10251032
use lightning::types::payment::PaymentHash;
10261033
use lightning::util::config::UserConfig;
@@ -1032,7 +1039,7 @@ mod tests {
10321039
SCORER_PERSISTENCE_SECONDARY_NAMESPACE,
10331040
};
10341041
use lightning::util::ser::Writeable;
1035-
use lightning::util::sweep::{OutputSpendStatus, OutputSweeper, PRUNE_DELAY_BLOCKS};
1042+
use lightning::util::sweep::{OutputSpendStatus, OutputSweeperSync, PRUNE_DELAY_BLOCKS};
10361043
use lightning::util::test_utils;
10371044
use lightning::{get_event, get_event_msg};
10381045
use lightning_persister::fs_store::FilesystemStore;
@@ -1153,7 +1160,7 @@ mod tests {
11531160
best_block: BestBlock,
11541161
scorer: Arc<LockingWrapper<TestScorer>>,
11551162
sweeper: Arc<
1156-
OutputSweeper<
1163+
OutputSweeperSync<
11571164
Arc<test_utils::TestBroadcaster>,
11581165
Arc<TestWallet>,
11591166
Arc<test_utils::TestFeeEstimator>,
@@ -1454,7 +1461,7 @@ mod tests {
14541461

14551462
struct TestWallet {}
14561463

1457-
impl ChangeDestinationSource for TestWallet {
1464+
impl ChangeDestinationSourceSync for TestWallet {
14581465
fn get_change_destination_script(&self) -> Result<ScriptBuf, ()> {
14591466
Ok(ScriptBuf::new())
14601467
}
@@ -1533,7 +1540,7 @@ mod tests {
15331540
IgnoringMessageHandler {},
15341541
));
15351542
let wallet = Arc::new(TestWallet {});
1536-
let sweeper = Arc::new(OutputSweeper::new(
1543+
let sweeper = Arc::new(OutputSweeperSync::new(
15371544
best_block,
15381545
Arc::clone(&tx_broadcaster),
15391546
Arc::clone(&fee_estimator),
@@ -1938,7 +1945,7 @@ mod tests {
19381945
Some(nodes[0].messenger.clone()),
19391946
nodes[0].rapid_gossip_sync(),
19401947
nodes[0].peer_manager.clone(),
1941-
Some(nodes[0].sweeper.clone()),
1948+
Some(nodes[0].sweeper.sweeper_async()),
19421949
nodes[0].logger.clone(),
19431950
Some(nodes[0].scorer.clone()),
19441951
move |dur: Duration| {
@@ -2438,7 +2445,7 @@ mod tests {
24382445
Some(nodes[0].messenger.clone()),
24392446
nodes[0].rapid_gossip_sync(),
24402447
nodes[0].peer_manager.clone(),
2441-
Some(nodes[0].sweeper.clone()),
2448+
Some(nodes[0].sweeper.sweeper_async()),
24422449
nodes[0].logger.clone(),
24432450
Some(nodes[0].scorer.clone()),
24442451
move |dur: Duration| {
@@ -2652,7 +2659,7 @@ mod tests {
26522659
Some(nodes[0].messenger.clone()),
26532660
nodes[0].no_gossip_sync(),
26542661
nodes[0].peer_manager.clone(),
2655-
Some(nodes[0].sweeper.clone()),
2662+
Some(nodes[0].sweeper.sweeper_async()),
26562663
nodes[0].logger.clone(),
26572664
Some(nodes[0].scorer.clone()),
26582665
move |dur: Duration| {

Diff for: lightning/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
//! * `grind_signatures`
3131
3232
#![cfg_attr(not(any(test, fuzzing, feature = "_test_utils")), deny(missing_docs))]
33-
#![cfg_attr(not(any(test, feature = "_test_utils")), forbid(unsafe_code))]
3433

3534
#![deny(rustdoc::broken_intra_doc_links)]
3635
#![deny(rustdoc::private_intra_doc_links)]

Diff for: lightning/src/sign/mod.rs

+45
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ use crate::sign::ecdsa::EcdsaChannelSigner;
6767
use crate::sign::taproot::TaprootChannelSigner;
6868
use crate::util::atomic_counter::AtomicCounter;
6969
use core::convert::TryInto;
70+
use core::future::Future;
71+
use core::ops::Deref;
72+
use core::pin::Pin;
7073
use core::sync::atomic::{AtomicUsize, Ordering};
7174
#[cfg(taproot)]
7275
use musig2::types::{PartialSignature, PublicNonce};
@@ -975,17 +978,59 @@ pub trait SignerProvider {
975978
fn get_shutdown_scriptpubkey(&self) -> Result<ShutdownScript, ()>;
976979
}
977980

981+
/// Result type for `BlockSource` requests.
982+
pub type GetChangeDestinationScriptResult<T> = Result<T, ()>;
983+
984+
/// A type alias for a future that returns a [`GetChangeDestinationScriptResult`].
985+
pub type AsyncGetChangeDestinationScriptResult<'a, T> =
986+
Pin<Box<dyn Future<Output = GetChangeDestinationScriptResult<T>> + 'a + Send>>;
987+
978988
/// A helper trait that describes an on-chain wallet capable of returning a (change) destination
979989
/// script.
980990
pub trait ChangeDestinationSource {
981991
/// Returns a script pubkey which can be used as a change destination for
982992
/// [`OutputSpender::spend_spendable_outputs`].
983993
///
994+
/// This method should return a different value each time it is called, to avoid linking
995+
/// on-chain funds controlled to the same user.
996+
fn get_change_destination_script<'a>(
997+
&self,
998+
) -> AsyncGetChangeDestinationScriptResult<'a, ScriptBuf>;
999+
}
1000+
1001+
/// A synchronous helper trait that describes an on-chain wallet capable of returning a (change) destination script.
1002+
pub trait ChangeDestinationSourceSync {
9841003
/// This method should return a different value each time it is called, to avoid linking
9851004
/// on-chain funds controlled to the same user.
9861005
fn get_change_destination_script(&self) -> Result<ScriptBuf, ()>;
9871006
}
9881007

1008+
/// A wrapper around [`ChangeDestinationSource`] to allow for async calls.
1009+
pub struct ChangeDestinationSourceSyncWrapper<T: Deref>(T)
1010+
where
1011+
T::Target: ChangeDestinationSourceSync;
1012+
1013+
impl<T: Deref> ChangeDestinationSourceSyncWrapper<T>
1014+
where
1015+
T::Target: ChangeDestinationSourceSync,
1016+
{
1017+
/// Creates a new [`ChangeDestinationSourceSyncWrapper`].
1018+
pub fn new(source: T) -> Self {
1019+
Self(source)
1020+
}
1021+
}
1022+
impl<T: Deref> ChangeDestinationSource for ChangeDestinationSourceSyncWrapper<T>
1023+
where
1024+
T::Target: ChangeDestinationSourceSync,
1025+
{
1026+
fn get_change_destination_script<'a>(
1027+
&self,
1028+
) -> AsyncGetChangeDestinationScriptResult<'a, ScriptBuf> {
1029+
let script = self.0.get_change_destination_script();
1030+
Box::pin(async move { script })
1031+
}
1032+
}
1033+
9891034
mod sealed {
9901035
use bitcoin::secp256k1::{Scalar, SecretKey};
9911036

Diff for: lightning/src/util/async_poll.rs

+20-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use crate::prelude::*;
1313
use core::future::Future;
1414
use core::marker::Unpin;
1515
use core::pin::Pin;
16-
use core::task::{Context, Poll};
16+
use core::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
1717

1818
pub(crate) enum ResultFuture<F: Future<Output = Result<(), E>>, E: Copy + Unpin> {
1919
Pending(F),
@@ -74,3 +74,22 @@ impl<F: Future<Output = Result<(), E>> + Unpin, E: Copy + Unpin> Future
7474
}
7575
}
7676
}
77+
78+
// If we want to poll a future without an async context to figure out if it has completed or
79+
// not without awaiting, we need a Waker, which needs a vtable...we fill it with dummy values
80+
// but sadly there's a good bit of boilerplate here.
81+
fn dummy_waker_clone(_: *const ()) -> RawWaker {
82+
RawWaker::new(core::ptr::null(), &DUMMY_WAKER_VTABLE)
83+
}
84+
fn dummy_waker_action(_: *const ()) {}
85+
86+
const DUMMY_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(
87+
dummy_waker_clone,
88+
dummy_waker_action,
89+
dummy_waker_action,
90+
dummy_waker_action,
91+
);
92+
93+
pub(crate) fn dummy_waker() -> Waker {
94+
unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &DUMMY_WAKER_VTABLE)) }
95+
}

0 commit comments

Comments
 (0)