Drop Deref indirection for OutputSpender
What changed, and why it matters
This is a routine Rust code cleanup change. It removes the requirement that an OutputSpender must be wrapped in a Deref pointer (like Arc or reference), and instead makes OutputSpender work directly through a blanket implementation. The commit message says it reduces generics and verbosity while keeping the same behavior. There is no security fix here.
No security action needed. Treat as normal code maintenance.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch refactors trait bounds from O: Deref where O::Target: OutputSpender to O: OutputSpender across background processor, signer, and sweeper modules. A blanket impl impl<T: OutputSpender + ?Sized, O: Deref<Target = T>> OutputSpender for O is added so that smart pointers/references to OutputSpender still implement OutputSpender. This is a pure ergonomics/refactoring change with no functional or security behavior change.
Changed components
lightning-background-processor/src/lib.rslightning/src/sign/mod.rslightning/src/util/sweep.rsInspect captured patch +30 / −26
diff --git a/lightning-background-processor/src/lib.rs b/lightning-background-processor/src/lib.rs
index 905782c..d765cca 100644
--- a/lightning-background-processor/src/lib.rs
+++ b/lightning-background-processor/src/lib.rs
@@ -946,7 +946,7 @@ pub async fn process_events_async<
PM: Deref,
LM: Deref,
D: Deref,
- O: Deref,
+ O: OutputSpender,
K: KVStore,
OS: Deref<Target = OutputSweeper<T, D, F, CF, K, L, O>>,
S: Deref<Target = SC>,
@@ -967,7 +967,6 @@ where
OM::Target: AOnionMessenger,
PM::Target: APeerManager,
LM::Target: ALiquidityManager,
- O::Target: OutputSpender,
D::Target: ChangeDestinationSource,
{
let async_event_handler = |event| {
@@ -1441,7 +1440,7 @@ pub async fn process_events_async_with_kv_store_sync<
PM: Deref,
LM: Deref,
D: Deref,
- O: Deref,
+ O: OutputSpender,
K: Deref,
OS: Deref<Target = OutputSweeperSync<T, D, F, CF, K, L, O>>,
S: Deref<Target = SC>,
@@ -1462,7 +1461,6 @@ where
OM::Target: AOnionMessenger,
PM::Target: APeerManager,
LM::Target: ALiquidityManager,
- O::Target: OutputSpender,
D::Target: ChangeDestinationSourceSync,
K::Target: KVStoreSync,
{
@@ -1556,7 +1554,7 @@ impl BackgroundProcessor {
S: 'static + Deref<Target = SC> + Send + Sync,
SC: for<'b> WriteableScore<'b>,
D: 'static + Deref,
- O: 'static + Deref,
+ O: 'static + OutputSpender,
K: 'static + Deref + Send,
OS: 'static + Deref<Target = OutputSweeperSync<T, D, F, CF, K, L, O>> + Send,
>(
@@ -1573,7 +1571,6 @@ impl BackgroundProcessor {
PM::Target: APeerManager,
LM::Target: ALiquidityManagerSync,
D::Target: ChangeDestinationSourceSync,
- O::Target: 'static + OutputSpender,
K::Target: 'static + KVStoreSync,
{
let stop_thread = Arc::new(AtomicBool::new(false));
diff --git a/lightning/src/sign/mod.rs b/lightning/src/sign/mod.rs
index f4f4c5c..84bfbb9 100644
--- a/lightning/src/sign/mod.rs
+++ b/lightning/src/sign/mod.rs
@@ -1063,6 +1063,23 @@ pub trait OutputSpender {
) -> Result<Transaction, ()>;
}
+impl<T: OutputSpender + ?Sized, O: Deref<Target = T>> OutputSpender for O {
+ fn spend_spendable_outputs(
+ &self, descriptors: &[&SpendableOutputDescriptor], outputs: Vec<TxOut>,
+ change_destination_script: ScriptBuf, feerate_sat_per_1000_weight: u32,
+ locktime: Option<LockTime>, secp_ctx: &Secp256k1<All>,
+ ) -> Result<Transaction, ()> {
+ self.deref().spend_spendable_outputs(
+ descriptors,
+ outputs,
+ change_destination_script,
+ feerate_sat_per_1000_weight,
+ locktime,
+ secp_ctx,
+ )
+ }
+}
+
// Primarily needed in doctests because of https://github.com/rust-lang/rust/issues/67295
/// A dynamic [`SignerProvider`] temporarily needed for doc tests.
///
diff --git a/lightning/src/util/sweep.rs b/lightning/src/util/sweep.rs
index e69b3a9..2aef218 100644
--- a/lightning/src/util/sweep.rs
+++ b/lightning/src/util/sweep.rs
@@ -344,10 +344,9 @@ pub struct OutputSweeper<
F: Filter,
K: KVStore,
L: Logger,
- O: Deref,
+ O: OutputSpender,
> where
D::Target: ChangeDestinationSource,
- O::Target: OutputSpender,
{
sweeper_state: Mutex<SweeperState>,
pending_sweep: AtomicBool,
@@ -367,11 +366,10 @@ impl<
F: Filter,
K: KVStore,
L: Logger,
- O: Deref,
+ O: OutputSpender,
> OutputSweeper<B, D, E, F, K, L, O>
where
D::Target: ChangeDestinationSource,
- O::Target: OutputSpender,
{
/// Constructs a new [`OutputSweeper`].
///
@@ -721,11 +719,10 @@ impl<
F: Filter + Sync + Send,
K: KVStore,
L: Logger,
- O: Deref,
+ O: OutputSpender,
> Listen for OutputSweeper<B, D, E, F, K, L, O>
where
D::Target: ChangeDestinationSource,
- O::Target: OutputSpender,
{
fn filtered_block_connected(
&self, header: &Header, txdata: &chain::transaction::TransactionData, height: u32,
@@ -764,11 +761,10 @@ impl<
F: Filter + Sync + Send,
K: KVStore,
L: Logger,
- O: Deref,
+ O: OutputSpender,
> Confirm for OutputSweeper<B, D, E, F, K, L, O>
where
D::Target: ChangeDestinationSource,
- O::Target: OutputSpender,
{
fn transactions_confirmed(
&self, header: &Header, txdata: &chain::transaction::TransactionData, height: u32,
@@ -863,11 +859,10 @@ impl<
F: Filter + Sync + Send,
K: KVStore,
L: Logger,
- O: Deref,
+ O: OutputSpender,
> ReadableArgs<(B, E, Option<F>, O, D, K, L)> for (BestBlock, OutputSweeper<B, D, E, F, K, L, O>)
where
D::Target: ChangeDestinationSource,
- O::Target: OutputSpender,
{
#[inline]
fn read<R: io::Read>(
@@ -935,11 +930,10 @@ pub struct OutputSweeperSync<
F: Filter,
K: Deref,
L: Logger,
- O: Deref,
+ O: OutputSpender,
> where
D::Target: ChangeDestinationSourceSync,
K::Target: KVStoreSync,
- O::Target: OutputSpender,
{
sweeper:
OutputSweeper<B, ChangeDestinationSourceSyncWrapper<D>, E, F, KVStoreSyncWrapper<K>, L, O>,
@@ -952,12 +946,11 @@ impl<
F: Filter,
K: Deref,
L: Logger,
- O: Deref,
+ O: OutputSpender,
> OutputSweeperSync<B, D, E, F, K, L, O>
where
D::Target: ChangeDestinationSourceSync,
K::Target: KVStoreSync,
- O::Target: OutputSpender,
{
/// Constructs a new [`OutputSweeperSync`] instance.
///
@@ -1075,12 +1068,11 @@ impl<
F: Filter + Sync + Send,
K: Deref,
L: Logger,
- O: Deref,
+ O: OutputSpender,
> Listen for OutputSweeperSync<B, D, E, F, K, L, O>
where
D::Target: ChangeDestinationSourceSync,
K::Target: KVStoreSync,
- O::Target: OutputSpender,
{
fn filtered_block_connected(
&self, header: &Header, txdata: &chain::transaction::TransactionData, height: u32,
@@ -1100,12 +1092,11 @@ impl<
F: Filter + Sync + Send,
K: Deref,
L: Logger,
- O: Deref,
+ O: OutputSpender,
> Confirm for OutputSweeperSync<B, D, E, F, K, L, O>
where
D::Target: ChangeDestinationSourceSync,
K::Target: KVStoreSync,
- O::Target: OutputSpender,
{
fn transactions_confirmed(
&self, header: &Header, txdata: &chain::transaction::TransactionData, height: u32,
@@ -1133,13 +1124,12 @@ impl<
F: Filter + Sync + Send,
K: Deref,
L: Logger,
- O: Deref,
+ O: OutputSpender,
> ReadableArgs<(B, E, Option<F>, O, D, K, L)>
for (BestBlock, OutputSweeperSync<B, D, E, F, K, L, O>)
where
D::Target: ChangeDestinationSourceSync,
K::Target: KVStoreSync,
- O::Target: OutputSpender,
{
#[inline]
fn read<R: io::Read>(
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.