Skip to content

Commit 319bda9

Browse files
committed
Drop required Boxing of lightning-block-sync Futures
Now that our MSRV is 1.75, we can return `impl Trait` from trait methods. Here we use this to clean up `lightning-block-sync` trait methods, dropping the `Pin<Box<dyn ...>>` we had to use to have trait methods return a concrete type.
1 parent fb9e979 commit 319bda9

File tree

6 files changed

+101
-92
lines changed

6 files changed

+101
-92
lines changed

lightning-block-sync/src/gossip.rs

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//! current UTXO set. This module defines an implementation of the LDK API required to do so
33
//! against a [`BlockSource`] which implements a few additional methods for accessing the UTXO set.
44
5-
use crate::{AsyncBlockSourceResult, BlockData, BlockSource, BlockSourceError};
5+
use crate::{BlockData, BlockSource, BlockSourceError, BlockSourceResult};
66

77
use bitcoin::block::Block;
88
use bitcoin::constants::ChainHash;
@@ -18,7 +18,7 @@ use lightning::util::native_async::FutureSpawner;
1818
use std::collections::VecDeque;
1919
use std::future::Future;
2020
use std::ops::Deref;
21-
use std::pin::Pin;
21+
use std::pin::{pin, Pin};
2222
use std::sync::{Arc, Mutex};
2323
use std::task::Poll;
2424

@@ -35,11 +35,13 @@ pub trait UtxoSource: BlockSource + 'static {
3535
/// for gossip validation.
3636
fn get_block_hash_by_height<'a>(
3737
&'a self, block_height: u32,
38-
) -> AsyncBlockSourceResult<'a, BlockHash>;
38+
) -> impl Future<Output = BlockSourceResult<BlockHash>> + Send + 'a;
3939

4040
/// Returns true if the given output has *not* been spent, i.e. is a member of the current UTXO
4141
/// set.
42-
fn is_output_unspent<'a>(&'a self, outpoint: OutPoint) -> AsyncBlockSourceResult<'a, bool>;
42+
fn is_output_unspent<'a>(
43+
&'a self, outpoint: OutPoint,
44+
) -> impl Future<Output = BlockSourceResult<bool>> + Send + 'a;
4345
}
4446

4547
#[cfg(feature = "tokio")]
@@ -55,34 +57,37 @@ impl FutureSpawner for TokioSpawner {
5557
/// A trivial future which joins two other futures and polls them at the same time, returning only
5658
/// once both complete.
5759
pub(crate) struct Joiner<
58-
A: Future<Output = Result<(BlockHash, Option<u32>), BlockSourceError>> + Unpin,
59-
B: Future<Output = Result<BlockHash, BlockSourceError>> + Unpin,
60+
'a,
61+
A: Future<Output = Result<(BlockHash, Option<u32>), BlockSourceError>>,
62+
B: Future<Output = Result<BlockHash, BlockSourceError>>,
6063
> {
61-
pub a: A,
62-
pub b: B,
64+
pub a: Pin<&'a mut A>,
65+
pub b: Pin<&'a mut B>,
6366
a_res: Option<(BlockHash, Option<u32>)>,
6467
b_res: Option<BlockHash>,
6568
}
6669

6770
impl<
68-
A: Future<Output = Result<(BlockHash, Option<u32>), BlockSourceError>> + Unpin,
69-
B: Future<Output = Result<BlockHash, BlockSourceError>> + Unpin,
70-
> Joiner<A, B>
71+
'a,
72+
A: Future<Output = Result<(BlockHash, Option<u32>), BlockSourceError>>,
73+
B: Future<Output = Result<BlockHash, BlockSourceError>>,
74+
> Joiner<'a, A, B>
7175
{
72-
fn new(a: A, b: B) -> Self {
76+
fn new(a: Pin<&'a mut A>, b: Pin<&'a mut B>) -> Self {
7377
Self { a, b, a_res: None, b_res: None }
7478
}
7579
}
7680

7781
impl<
78-
A: Future<Output = Result<(BlockHash, Option<u32>), BlockSourceError>> + Unpin,
79-
B: Future<Output = Result<BlockHash, BlockSourceError>> + Unpin,
80-
> Future for Joiner<A, B>
82+
'a,
83+
A: Future<Output = Result<(BlockHash, Option<u32>), BlockSourceError>>,
84+
B: Future<Output = Result<BlockHash, BlockSourceError>>,
85+
> Future for Joiner<'a, A, B>
8186
{
8287
type Output = Result<((BlockHash, Option<u32>), BlockHash), BlockSourceError>;
8388
fn poll(mut self: Pin<&mut Self>, ctx: &mut core::task::Context<'_>) -> Poll<Self::Output> {
8489
if self.a_res.is_none() {
85-
match Pin::new(&mut self.a).poll(ctx) {
90+
match self.a.as_mut().poll(ctx) {
8691
Poll::Ready(res) => {
8792
if let Ok(ok) = res {
8893
self.a_res = Some(ok);
@@ -94,7 +99,7 @@ impl<
9499
}
95100
}
96101
if self.b_res.is_none() {
97-
match Pin::new(&mut self.b).poll(ctx) {
102+
match self.b.as_mut().poll(ctx) {
98103
Poll::Ready(res) => {
99104
if let Ok(ok) = res {
100105
self.b_res = Some(ok);
@@ -200,10 +205,12 @@ where
200205
}
201206
}
202207

203-
let ((_, tip_height_opt), block_hash) =
204-
Joiner::new(source.get_best_block(), source.get_block_hash_by_height(block_height))
205-
.await
206-
.map_err(|_| UtxoLookupError::UnknownTx)?;
208+
let ((_, tip_height_opt), block_hash) = Joiner::new(
209+
pin!(source.get_best_block()),
210+
pin!(source.get_block_hash_by_height(block_height)),
211+
)
212+
.await
213+
.map_err(|_| UtxoLookupError::UnknownTx)?;
207214
if let Some(tip_height) = tip_height_opt {
208215
// If the block doesn't yet have five confirmations, error out.
209216
//

lightning-block-sync/src/lib.rs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ use lightning::chain::{BestBlock, Listen};
5353

5454
use std::future::Future;
5555
use std::ops::Deref;
56-
use std::pin::Pin;
5756

5857
/// Abstract type for retrieving block headers and data.
5958
pub trait BlockSource: Sync + Send {
@@ -65,31 +64,28 @@ pub trait BlockSource: Sync + Send {
6564
/// when `height_hint` is `None`.
6665
fn get_header<'a>(
6766
&'a self, header_hash: &'a BlockHash, height_hint: Option<u32>,
68-
) -> AsyncBlockSourceResult<'a, BlockHeaderData>;
67+
) -> impl Future<Output = BlockSourceResult<BlockHeaderData>> + Send + 'a;
6968

7069
/// Returns the block for a given hash. A headers-only block source should return a `Transient`
7170
/// error.
72-
fn get_block<'a>(&'a self, header_hash: &'a BlockHash)
73-
-> AsyncBlockSourceResult<'a, BlockData>;
71+
fn get_block<'a>(
72+
&'a self, header_hash: &'a BlockHash,
73+
) -> impl Future<Output = BlockSourceResult<BlockData>> + Send + 'a;
7474

7575
/// Returns the hash of the best block and, optionally, its height.
7676
///
7777
/// When polling a block source, [`Poll`] implementations may pass the height to [`get_header`]
7878
/// to allow for a more efficient lookup.
7979
///
8080
/// [`get_header`]: Self::get_header
81-
fn get_best_block(&self) -> AsyncBlockSourceResult<'_, (BlockHash, Option<u32>)>;
81+
fn get_best_block<'a>(
82+
&'a self,
83+
) -> impl Future<Output = BlockSourceResult<(BlockHash, Option<u32>)>> + Send + 'a;
8284
}
8385

8486
/// Result type for `BlockSource` requests.
8587
pub type BlockSourceResult<T> = Result<T, BlockSourceError>;
8688

87-
// TODO: Replace with BlockSourceResult once `async` trait functions are supported. For details,
88-
// see: https://areweasyncyet.rs.
89-
/// Result type for asynchronous `BlockSource` requests.
90-
pub type AsyncBlockSourceResult<'a, T> =
91-
Pin<Box<dyn Future<Output = BlockSourceResult<T>> + 'a + Send>>;
92-
9389
/// Error type for `BlockSource` requests.
9490
///
9591
/// Transient errors may be resolved when re-polling, but no attempt will be made to re-poll on

lightning-block-sync/src/poll.rs

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
//! Adapters that make one or more [`BlockSource`]s simpler to poll for new chain tip transitions.
22
3-
use crate::{
4-
AsyncBlockSourceResult, BlockData, BlockHeaderData, BlockSource, BlockSourceError,
5-
BlockSourceResult,
6-
};
3+
use crate::{BlockData, BlockHeaderData, BlockSource, BlockSourceError, BlockSourceResult};
74

85
use bitcoin::hash_types::BlockHash;
96
use bitcoin::network::Network;
107
use lightning::chain::BestBlock;
118

9+
use std::future::Future;
1210
use std::ops::Deref;
1311

1412
/// The `Poll` trait defines behavior for polling block sources for a chain tip and retrieving
@@ -22,17 +20,17 @@ pub trait Poll {
2220
/// Returns a chain tip in terms of its relationship to the provided chain tip.
2321
fn poll_chain_tip<'a>(
2422
&'a self, best_known_chain_tip: ValidatedBlockHeader,
25-
) -> AsyncBlockSourceResult<'a, ChainTip>;
23+
) -> impl Future<Output = BlockSourceResult<ChainTip>> + Send + 'a;
2624

2725
/// Returns the header that preceded the given header in the chain.
2826
fn look_up_previous_header<'a>(
2927
&'a self, header: &'a ValidatedBlockHeader,
30-
) -> AsyncBlockSourceResult<'a, ValidatedBlockHeader>;
28+
) -> impl Future<Output = BlockSourceResult<ValidatedBlockHeader>> + Send + 'a;
3129

3230
/// Returns the block associated with the given header.
3331
fn fetch_block<'a>(
3432
&'a self, header: &'a ValidatedBlockHeader,
35-
) -> AsyncBlockSourceResult<'a, ValidatedBlock>;
33+
) -> impl Future<Output = BlockSourceResult<ValidatedBlock>> + Send + 'a;
3634
}
3735

3836
/// A chain tip relative to another chain tip in terms of block hash and chainwork.
@@ -217,8 +215,8 @@ impl<B: Deref<Target = T> + Sized + Send + Sync, T: BlockSource + ?Sized> Poll
217215
{
218216
fn poll_chain_tip<'a>(
219217
&'a self, best_known_chain_tip: ValidatedBlockHeader,
220-
) -> AsyncBlockSourceResult<'a, ChainTip> {
221-
Box::pin(async move {
218+
) -> impl Future<Output = BlockSourceResult<ChainTip>> + Send + 'a {
219+
async move {
222220
let (block_hash, height) = self.block_source.get_best_block().await?;
223221
if block_hash == best_known_chain_tip.header.block_hash() {
224222
return Ok(ChainTip::Common);
@@ -231,13 +229,13 @@ impl<B: Deref<Target = T> + Sized + Send + Sync, T: BlockSource + ?Sized> Poll
231229
} else {
232230
Ok(ChainTip::Worse(chain_tip))
233231
}
234-
})
232+
}
235233
}
236234

237235
fn look_up_previous_header<'a>(
238236
&'a self, header: &'a ValidatedBlockHeader,
239-
) -> AsyncBlockSourceResult<'a, ValidatedBlockHeader> {
240-
Box::pin(async move {
237+
) -> impl Future<Output = BlockSourceResult<ValidatedBlockHeader>> + Send + 'a {
238+
async move {
241239
if header.height == 0 {
242240
return Err(BlockSourceError::persistent("genesis block reached"));
243241
}
@@ -252,15 +250,13 @@ impl<B: Deref<Target = T> + Sized + Send + Sync, T: BlockSource + ?Sized> Poll
252250
header.check_builds_on(&previous_header, self.network)?;
253251

254252
Ok(previous_header)
255-
})
253+
}
256254
}
257255

258256
fn fetch_block<'a>(
259257
&'a self, header: &'a ValidatedBlockHeader,
260-
) -> AsyncBlockSourceResult<'a, ValidatedBlock> {
261-
Box::pin(async move {
262-
self.block_source.get_block(&header.block_hash).await?.validate(header.block_hash)
263-
})
258+
) -> impl Future<Output = BlockSourceResult<ValidatedBlock>> + Send + 'a {
259+
async move { self.block_source.get_block(&header.block_hash).await?.validate(header.block_hash) }
264260
}
265261
}
266262

lightning-block-sync/src/rest.rs

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@
44
use crate::convert::GetUtxosResponse;
55
use crate::gossip::UtxoSource;
66
use crate::http::{BinaryResponse, HttpClient, HttpEndpoint, JsonResponse};
7-
use crate::{AsyncBlockSourceResult, BlockData, BlockHeaderData, BlockSource};
7+
use crate::{BlockData, BlockHeaderData, BlockSource, BlockSourceResult};
88

99
use bitcoin::hash_types::BlockHash;
1010
use bitcoin::OutPoint;
1111

1212
use std::convert::TryFrom;
1313
use std::convert::TryInto;
14+
use std::future::Future;
1415
use std::sync::Mutex;
1516

1617
/// A simple REST client for requesting resources using HTTP `GET`.
@@ -49,49 +50,51 @@ impl RestClient {
4950
impl BlockSource for RestClient {
5051
fn get_header<'a>(
5152
&'a self, header_hash: &'a BlockHash, _height: Option<u32>,
52-
) -> AsyncBlockSourceResult<'a, BlockHeaderData> {
53-
Box::pin(async move {
53+
) -> impl Future<Output = BlockSourceResult<BlockHeaderData>> + Send + 'a {
54+
async move {
5455
let resource_path = format!("headers/1/{}.json", header_hash.to_string());
5556
Ok(self.request_resource::<JsonResponse, _>(&resource_path).await?)
56-
})
57+
}
5758
}
5859

5960
fn get_block<'a>(
6061
&'a self, header_hash: &'a BlockHash,
61-
) -> AsyncBlockSourceResult<'a, BlockData> {
62-
Box::pin(async move {
62+
) -> impl Future<Output = BlockSourceResult<BlockData>> + Send + 'a {
63+
async move {
6364
let resource_path = format!("block/{}.bin", header_hash.to_string());
6465
Ok(BlockData::FullBlock(
6566
self.request_resource::<BinaryResponse, _>(&resource_path).await?,
6667
))
67-
})
68+
}
6869
}
6970

70-
fn get_best_block<'a>(&'a self) -> AsyncBlockSourceResult<'a, (BlockHash, Option<u32>)> {
71-
Box::pin(
72-
async move { Ok(self.request_resource::<JsonResponse, _>("chaininfo.json").await?) },
73-
)
71+
fn get_best_block<'a>(
72+
&'a self,
73+
) -> impl Future<Output = BlockSourceResult<(BlockHash, Option<u32>)>> + Send + 'a {
74+
async move { Ok(self.request_resource::<JsonResponse, _>("chaininfo.json").await?) }
7475
}
7576
}
7677

7778
impl UtxoSource for RestClient {
7879
fn get_block_hash_by_height<'a>(
7980
&'a self, block_height: u32,
80-
) -> AsyncBlockSourceResult<'a, BlockHash> {
81-
Box::pin(async move {
81+
) -> impl Future<Output = BlockSourceResult<BlockHash>> + Send + 'a {
82+
async move {
8283
let resource_path = format!("blockhashbyheight/{}.bin", block_height);
8384
Ok(self.request_resource::<BinaryResponse, _>(&resource_path).await?)
84-
})
85+
}
8586
}
8687

87-
fn is_output_unspent<'a>(&'a self, outpoint: OutPoint) -> AsyncBlockSourceResult<'a, bool> {
88-
Box::pin(async move {
88+
fn is_output_unspent<'a>(
89+
&'a self, outpoint: OutPoint,
90+
) -> impl Future<Output = BlockSourceResult<bool>> + Send + 'a {
91+
async move {
8992
let resource_path =
9093
format!("getutxos/{}-{}.json", outpoint.txid.to_string(), outpoint.vout);
9194
let utxo_result =
9295
self.request_resource::<JsonResponse, GetUtxosResponse>(&resource_path).await?;
9396
Ok(utxo_result.hit_bitmap_nonempty)
94-
})
97+
}
9598
}
9699
}
97100

0 commit comments

Comments
 (0)