Trivially replace `Box::pin` with `pin!` in a few places
What changed, and why it matters
This commit is a routine code cleanup that swaps one Rust standard-library mechanism for pinning futures (`Box::pin`) with a newer, allocation-free equivalent (`pin!`). It removes heap allocations in a few internal loops and sync wrappers, but does not change program logic, trust boundaries, or behavior. There is no security relevance.
No security action required. Treat as a normal performance/refactoring commit.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The diff replaces Box::pin(...) calls with the stack-pinning core::pin::pin! macro (stabilized in Rust 1.68) across six files. Affected sites are synchronous wrappers that poll an inner async future once with a dummy waker (lightning-liquidity, lightning/src/events/bump_transaction/sync.rs, lightning/src/util/persist.rs, lightning/src/util/sweep.rs) and the tokio network connection select loop (lightning-net-tokio). The change removes Box imports and a TODO comment about future MSRV support. No API, control flow, or data-handling changes are introduced.
Changed components
lightning-liquidity/src/lsps2/service.rslightning-liquidity/src/manager.rslightning-net-tokio/src/lib.rslightning/src/events/bump_transaction/sync.rslightning/src/util/persist.rslightning/src/util/sweep.rsInspect captured patch +25 / −26
diff --git a/lightning-liquidity/src/lsps2/service.rs b/lightning-liquidity/src/lsps2/service.rs
index a6736e6..5c4bd63 100644
--- a/lightning-liquidity/src/lsps2/service.rs
+++ b/lightning-liquidity/src/lsps2/service.rs
@@ -9,7 +9,6 @@
//! Contains the main bLIP-52 / LSPS2 server-side object, [`LSPS2ServiceHandler`].
-use alloc::boxed::Box;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
use lightning::util::persist::KVStore;
@@ -17,6 +16,7 @@ use lightning::util::persist::KVStore;
use core::cmp::Ordering as CmpOrdering;
use core::future::Future as StdFuture;
use core::ops::Deref;
+use core::pin::pin;
use core::sync::atomic::{AtomicUsize, Ordering};
use core::task;
@@ -2173,7 +2173,7 @@ where
&self, counterparty_node_id: &PublicKey, request_id: LSPSRequestId, intercept_scid: u64,
cltv_expiry_delta: u32, client_trusts_lsp: bool, user_channel_id: u128,
) -> Result<(), APIError> {
- let mut fut = Box::pin(self.inner.invoice_parameters_generated(
+ let mut fut = pin!(self.inner.invoice_parameters_generated(
counterparty_node_id,
request_id,
intercept_scid,
@@ -2202,7 +2202,7 @@ where
&self, intercept_scid: u64, intercept_id: InterceptId, expected_outbound_amount_msat: u64,
payment_hash: PaymentHash,
) -> Result<(), APIError> {
- let mut fut = Box::pin(self.inner.htlc_intercepted(
+ let mut fut = pin!(self.inner.htlc_intercepted(
intercept_scid,
intercept_id,
expected_outbound_amount_msat,
@@ -2228,7 +2228,7 @@ where
pub fn htlc_handling_failed(
&self, failure_type: HTLCHandlingFailureType,
) -> Result<(), APIError> {
- let mut fut = Box::pin(self.inner.htlc_handling_failed(failure_type));
+ let mut fut = pin!(self.inner.htlc_handling_failed(failure_type));
let mut waker = dummy_waker();
let mut ctx = task::Context::from_waker(&mut waker);
@@ -2249,7 +2249,7 @@ where
pub fn payment_forwarded(
&self, next_channel_id: ChannelId, skimmed_fee_msat: u64,
) -> Result<(), APIError> {
- let mut fut = Box::pin(self.inner.payment_forwarded(next_channel_id, skimmed_fee_msat));
+ let mut fut = pin!(self.inner.payment_forwarded(next_channel_id, skimmed_fee_msat));
let mut waker = dummy_waker();
let mut ctx = task::Context::from_waker(&mut waker);
@@ -2290,7 +2290,7 @@ where
&self, counterparty_node_id: &PublicKey, user_channel_id: u128,
) -> Result<(), APIError> {
let mut fut =
- Box::pin(self.inner.channel_open_abandoned(counterparty_node_id, user_channel_id));
+ pin!(self.inner.channel_open_abandoned(counterparty_node_id, user_channel_id));
let mut waker = dummy_waker();
let mut ctx = task::Context::from_waker(&mut waker);
@@ -2309,8 +2309,7 @@ where
pub fn channel_open_failed(
&self, counterparty_node_id: &PublicKey, user_channel_id: u128,
) -> Result<(), APIError> {
- let mut fut =
- Box::pin(self.inner.channel_open_failed(counterparty_node_id, user_channel_id));
+ let mut fut = pin!(self.inner.channel_open_failed(counterparty_node_id, user_channel_id));
let mut waker = dummy_waker();
let mut ctx = task::Context::from_waker(&mut waker);
@@ -2332,7 +2331,7 @@ where
&self, user_channel_id: u128, channel_id: &ChannelId, counterparty_node_id: &PublicKey,
) -> Result<(), APIError> {
let mut fut =
- Box::pin(self.inner.channel_ready(user_channel_id, channel_id, counterparty_node_id));
+ pin!(self.inner.channel_ready(user_channel_id, channel_id, counterparty_node_id));
let mut waker = dummy_waker();
let mut ctx = task::Context::from_waker(&mut waker);
diff --git a/lightning-liquidity/src/manager.rs b/lightning-liquidity/src/manager.rs
index f0143fc..d382271 100644
--- a/lightning-liquidity/src/manager.rs
+++ b/lightning-liquidity/src/manager.rs
@@ -7,7 +7,6 @@
// You may not use this file except in accordance with one or both of these
// licenses.
-use alloc::boxed::Box;
use alloc::string::ToString;
use alloc::vec::Vec;
@@ -61,6 +60,7 @@ use bitcoin::secp256k1::PublicKey;
use core::future::Future as StdFuture;
use core::ops::Deref;
+use core::pin::pin;
use core::task;
const LSPS_FEATURE_BIT: usize = 729;
@@ -1106,7 +1106,7 @@ where
) -> Result<Self, lightning::io::Error> {
let kv_store = KVStoreSyncWrapper(kv_store_sync);
- let mut fut = Box::pin(LiquidityManager::new(
+ let mut fut = pin!(LiquidityManager::new(
entropy_source,
node_signer,
channel_manager,
@@ -1159,7 +1159,7 @@ where
client_config: Option<LiquidityClientConfig>, time_provider: TP,
) -> Result<Self, lightning::io::Error> {
let kv_store = KVStoreSyncWrapper(kv_store_sync);
- let mut fut = Box::pin(LiquidityManager::new_with_custom_time_provider(
+ let mut fut = pin!(LiquidityManager::new_with_custom_time_provider(
entropy_source,
node_signer,
channel_manager,
@@ -1289,7 +1289,7 @@ where
pub fn persist(&self) -> Result<(), lightning::io::Error> {
let mut waker = dummy_waker();
let mut ctx = task::Context::from_waker(&mut waker);
- match Box::pin(self.inner.persist()).as_mut().poll(&mut ctx) {
+ match pin!(self.inner.persist()).as_mut().poll(&mut ctx) {
task::Poll::Ready(result) => result,
task::Poll::Pending => {
// In a sync context, we can't wait for the future to complete.
diff --git a/lightning-net-tokio/src/lib.rs b/lightning-net-tokio/src/lib.rs
index 068f77a..c6fbd3d 100644
--- a/lightning-net-tokio/src/lib.rs
+++ b/lightning-net-tokio/src/lib.rs
@@ -43,7 +43,7 @@ use std::hash::Hash;
use std::net::SocketAddr;
use std::net::TcpStream as StdTcpStream;
use std::ops::Deref;
-use std::pin::Pin;
+use std::pin::{pin, Pin};
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::{Arc, Mutex};
use std::task::{self, Poll};
@@ -205,18 +205,17 @@ impl Connection {
}
us_lock.read_paused
};
- // TODO: Drop the Box'ing of the futures once Rust has pin-on-stack support.
let select_result = if read_paused {
TwoSelector {
- a: Box::pin(write_avail_receiver.recv()),
- b: Box::pin(read_wake_receiver.recv()),
+ a: pin!(write_avail_receiver.recv()),
+ b: pin!(read_wake_receiver.recv()),
}
.await
} else {
ThreeSelector {
- a: Box::pin(write_avail_receiver.recv()),
- b: Box::pin(read_wake_receiver.recv()),
- c: Box::pin(reader.readable()),
+ a: pin!(write_avail_receiver.recv()),
+ b: pin!(read_wake_receiver.recv()),
+ c: pin!(reader.readable()),
}
.await
};
diff --git a/lightning/src/events/bump_transaction/sync.rs b/lightning/src/events/bump_transaction/sync.rs
index 653710a..cbc686e 100644
--- a/lightning/src/events/bump_transaction/sync.rs
+++ b/lightning/src/events/bump_transaction/sync.rs
@@ -11,6 +11,7 @@
use core::future::Future;
use core::ops::Deref;
+use core::pin::pin;
use core::task;
use crate::chain::chaininterface::BroadcasterInterface;
@@ -289,7 +290,7 @@ where
/// Handles all variants of [`BumpTransactionEvent`].
pub fn handle_event(&self, event: &BumpTransactionEvent) {
- let mut fut = Box::pin(self.bump_transaction_event_handler.handle_event(event));
+ let mut fut = pin!(self.bump_transaction_event_handler.handle_event(event));
let mut waker = dummy_waker();
let mut ctx = task::Context::from_waker(&mut waker);
match fut.as_mut().poll(&mut ctx) {
diff --git a/lightning/src/util/persist.rs b/lightning/src/util/persist.rs
index d00e29e..3ad9b42 100644
--- a/lightning/src/util/persist.rs
+++ b/lightning/src/util/persist.rs
@@ -19,7 +19,7 @@ use bitcoin::{BlockHash, Txid};
use core::future::Future;
use core::mem;
use core::ops::Deref;
-use core::pin::Pin;
+use core::pin::{pin, Pin};
use core::str::FromStr;
use core::task;
@@ -490,8 +490,7 @@ impl FutureSpawner for PanicingSpawner {
fn poll_sync_future<F: Future>(future: F) -> F::Output {
let mut waker = dummy_waker();
let mut ctx = task::Context::from_waker(&mut waker);
- // TODO A future MSRV bump to 1.68 should allow for the pin macro
- match Pin::new(&mut Box::pin(future)).poll(&mut ctx) {
+ match pin!(future).poll(&mut ctx) {
task::Poll::Ready(result) => result,
task::Poll::Pending => {
// In a sync context, we can't wait for the future to complete.
diff --git a/lightning/src/util/sweep.rs b/lightning/src/util/sweep.rs
index 5a1ffad..a3ded6f 100644
--- a/lightning/src/util/sweep.rs
+++ b/lightning/src/util/sweep.rs
@@ -35,6 +35,7 @@ use bitcoin::{BlockHash, ScriptBuf, Transaction, Txid};
use core::future::Future;
use core::ops::Deref;
+use core::pin::pin;
use core::sync::atomic::{AtomicBool, Ordering};
use core::task;
@@ -970,7 +971,7 @@ where
&self, output_descriptors: Vec<SpendableOutputDescriptor>, channel_id: Option<ChannelId>,
exclude_static_outputs: bool, delay_until_height: Option<u32>,
) -> Result<(), ()> {
- let mut fut = Box::pin(self.sweeper.track_spendable_outputs(
+ let mut fut = pin!(self.sweeper.track_spendable_outputs(
output_descriptors,
channel_id,
exclude_static_outputs,
@@ -1005,7 +1006,7 @@ where
///
/// Wraps [`OutputSweeper::regenerate_and_broadcast_spend_if_necessary`].
pub fn regenerate_and_broadcast_spend_if_necessary(&self) -> Result<(), ()> {
- let mut fut = Box::pin(self.sweeper.regenerate_and_broadcast_spend_if_necessary());
+ let mut fut = pin!(self.sweeper.regenerate_and_broadcast_spend_if_necessary());
let mut waker = dummy_waker();
let mut ctx = task::Context::from_waker(&mut waker);
match fut.as_mut().poll(&mut ctx) {
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.