Drop Deref indirection for UtxoLookup
What changed, and why it matters
This is a routine Rust code cleanup change. It removes an unnecessary layer of pointer-like indirection (the Deref trait) from the UtxoLookup type used in Lightning gossip processing. The code now requires types to directly implement UtxoLookup, and adds a blanket implementation so that references and smart pointers to UtxoLookup implementers still work. There is no security-relevant behavior change visible in the diff.
No security action required. Treat as normal refactoring/code-quality change.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch refactors generic bounds across lightning-background-processor, lightning-block-sync, and lightning::routing from U: Deref where U::Target: UtxoLookup to U: UtxoLookup. To preserve ergonomics, a blanket impl is added in lightning/src/routing/utxo.rs: impl<T: UtxoLookup + ?Sized, U: Deref<Target = T>> UtxoLookup for U, which delegates get_utxo through Deref. This is a type-system simplification that should be behaviorally equivalent for callers. The GossipVerifier’s explicit Deref impl returning &Self is removed as it is no longer needed. No logic changes to UTXO validation, gossip verification, or channel announcement handling are present.
Changed components
lightning-background-processor/src/lib.rslightning-block-sync/src/gossip.rslightning/src/routing/gossip.rslightning/src/routing/utxo.rsInspect captured patch +30 / −65
diff --git a/lightning-background-processor/src/lib.rs b/lightning-background-processor/src/lib.rs
index d765cca..3bd3950 100644
--- a/lightning-background-processor/src/lib.rs
+++ b/lightning-background-processor/src/lib.rs
@@ -200,11 +200,9 @@ pub enum GossipSync<
P: Deref<Target = P2PGossipSync<G, U, L>>,
R: Deref<Target = RapidGossipSync<G, L>>,
G: Deref<Target = NetworkGraph<L>>,
- U: Deref,
+ U: UtxoLookup,
L: Logger,
-> where
- U::Target: UtxoLookup,
-{
+> {
/// Gossip sync via the lightning peer-to-peer network as defined by BOLT 7.
P2P(P),
/// Rapid gossip sync from a trusted server.
@@ -217,11 +215,9 @@ impl<
P: Deref<Target = P2PGossipSync<G, U, L>>,
R: Deref<Target = RapidGossipSync<G, L>>,
G: Deref<Target = NetworkGraph<L>>,
- U: Deref,
+ U: UtxoLookup,
L: Logger,
> GossipSync<P, R, G, U, L>
-where
- U::Target: UtxoLookup,
{
fn network_graph(&self) -> Option<&G> {
match self {
@@ -258,11 +254,9 @@ where
impl<
P: Deref<Target = P2PGossipSync<G, U, L>>,
G: Deref<Target = NetworkGraph<L>>,
- U: Deref,
+ U: UtxoLookup,
L: Logger,
> GossipSync<P, &RapidGossipSync<G, L>, G, U, L>
-where
- U::Target: UtxoLookup,
{
/// Initializes a new [`GossipSync::P2P`] variant.
pub fn p2p(gossip_sync: P) -> Self {
@@ -928,7 +922,7 @@ use futures_util::{dummy_waker, Joiner, OptionalSelector, Selector, SelectorOutp
///```
pub async fn process_events_async<
'a,
- UL: Deref,
+ UL: UtxoLookup,
CF: chain::Filter,
T: BroadcasterInterface,
F: FeeEstimator,
@@ -961,7 +955,6 @@ pub async fn process_events_async<
sleeper: Sleeper, mobile_interruptable_platform: bool, fetch_time: FetchTime,
) -> Result<(), lightning::io::Error>
where
- UL::Target: UtxoLookup,
P::Target: Persist<<CM::Target as AChannelManager>::Signer>,
CM::Target: AChannelManager,
OM::Target: AOnionMessenger,
@@ -1422,7 +1415,7 @@ fn check_and_reset_sleeper<
/// Async events processor that is based on [`process_events_async`] but allows for [`KVStoreSync`] to be used for
/// synchronous background persistence.
pub async fn process_events_async_with_kv_store_sync<
- UL: Deref,
+ UL: UtxoLookup,
CF: chain::Filter,
T: BroadcasterInterface,
F: FeeEstimator,
@@ -1455,7 +1448,6 @@ pub async fn process_events_async_with_kv_store_sync<
sleeper: Sleeper, mobile_interruptable_platform: bool, fetch_time: FetchTime,
) -> Result<(), lightning::io::Error>
where
- UL::Target: UtxoLookup,
P::Target: Persist<<CM::Target as AChannelManager>::Signer>,
CM::Target: AChannelManager,
OM::Target: AOnionMessenger,
@@ -1530,7 +1522,7 @@ impl BackgroundProcessor {
/// [`NetworkGraph::write`]: lightning::routing::gossip::NetworkGraph#impl-Writeable
pub fn start<
'a,
- UL: 'static + Deref,
+ UL: 'static + UtxoLookup,
CF: 'static + chain::Filter,
T: 'static + BroadcasterInterface,
F: 'static + FeeEstimator + Send,
@@ -1563,7 +1555,6 @@ impl BackgroundProcessor {
liquidity_manager: Option<LM>, sweeper: Option<OS>, logger: L, scorer: Option<S>,
) -> Self
where
- UL::Target: 'static + UtxoLookup,
L::Target: 'static + Logger,
P::Target: 'static + Persist<<CM::Target as AChannelManager>::Signer>,
CM::Target: AChannelManager,
diff --git a/lightning-block-sync/src/gossip.rs b/lightning-block-sync/src/gossip.rs
index 263fa40..477e278 100644
--- a/lightning-block-sync/src/gossip.rs
+++ b/lightning-block-sync/src/gossip.rs
@@ -239,16 +239,6 @@ where
}
}
-impl<S: FutureSpawner, Blocks: Deref + Send + Sync + Clone> Deref for GossipVerifier<S, Blocks>
-where
- Blocks::Target: UtxoSource,
-{
- type Target = Self;
- fn deref(&self) -> &Self {
- self
- }
-}
-
impl<S: FutureSpawner, Blocks: Deref + Send + Sync + Clone> UtxoLookup for GossipVerifier<S, Blocks>
where
Blocks::Target: UtxoSource,
diff --git a/lightning/src/routing/gossip.rs b/lightning/src/routing/gossip.rs
index b3059e3..d0b348d 100644
--- a/lightning/src/routing/gossip.rs
+++ b/lightning/src/routing/gossip.rs
@@ -319,10 +319,7 @@ impl MaybeReadable for NetworkUpdate {
/// This network graph is then used for routing payments.
/// Provides interface to help with initial routing sync by
/// serving historical announcements.
-pub struct P2PGossipSync<G: Deref<Target = NetworkGraph<L>>, U: Deref, L: Logger>
-where
- U::Target: UtxoLookup,
-{
+pub struct P2PGossipSync<G: Deref<Target = NetworkGraph<L>>, U: UtxoLookup, L: Logger> {
network_graph: G,
#[cfg(any(feature = "_test_utils", test))]
pub(super) utxo_lookup: Option<U>,
@@ -333,10 +330,7 @@ where
logger: L,
}
-impl<G: Deref<Target = NetworkGraph<L>>, U: Deref, L: Logger> P2PGossipSync<G, U, L>
-where
- U::Target: UtxoLookup,
-{
+impl<G: Deref<Target = NetworkGraph<L>>, U: UtxoLookup, L: Logger> P2PGossipSync<G, U, L> {
/// Creates a new tracker of the actual state of the network of channels and nodes,
/// assuming an existing [`NetworkGraph`].
///
@@ -534,10 +528,8 @@ pub fn verify_channel_announcement<C: Verification>(
Ok(())
}
-impl<G: Deref<Target = NetworkGraph<L>>, U: Deref, L: Logger> RoutingMessageHandler
+impl<G: Deref<Target = NetworkGraph<L>>, U: UtxoLookup, L: Logger> RoutingMessageHandler
for P2PGossipSync<G, U, L>
-where
- U::Target: UtxoLookup,
{
fn handle_node_announcement(
&self, _their_node_id: Option<PublicKey>, msg: &msgs::NodeAnnouncement,
@@ -761,10 +753,8 @@ where
}
}
-impl<G: Deref<Target = NetworkGraph<L>>, U: Deref, L: Logger> BaseMessageHandler
+impl<G: Deref<Target = NetworkGraph<L>>, U: UtxoLookup, L: Logger> BaseMessageHandler
for P2PGossipSync<G, U, L>
-where
- U::Target: UtxoLookup,
{
/// Initiates a stateless sync of routing gossip information with a peer
/// using [`gossip_queries`]. The default strategy used by this implementation
@@ -1972,12 +1962,9 @@ impl<L: Logger> NetworkGraph<L> {
///
/// If a [`UtxoLookup`] object is provided via `utxo_lookup`, it will be called to verify
/// the corresponding UTXO exists on chain and is correctly-formatted.
- pub fn update_channel_from_announcement<U: Deref>(
+ pub fn update_channel_from_announcement<U: UtxoLookup>(
&self, msg: &msgs::ChannelAnnouncement, utxo_lookup: &Option<U>,
- ) -> Result<(), LightningError>
- where
- U::Target: UtxoLookup,
- {
+ ) -> Result<(), LightningError> {
self.pre_channel_announcement_validation_check(&msg.contents, utxo_lookup)?;
verify_channel_announcement(msg, &self.secp_ctx)?;
self.update_channel_from_unsigned_announcement_intern(&msg.contents, Some(msg), utxo_lookup)
@@ -2002,12 +1989,9 @@ impl<L: Logger> NetworkGraph<L> {
///
/// If a [`UtxoLookup`] object is provided via `utxo_lookup`, it will be called to verify
/// the corresponding UTXO exists on chain and is correctly-formatted.
- pub fn update_channel_from_unsigned_announcement<U: Deref>(
+ pub fn update_channel_from_unsigned_announcement<U: UtxoLookup>(
&self, msg: &msgs::UnsignedChannelAnnouncement, utxo_lookup: &Option<U>,
- ) -> Result<(), LightningError>
- where
- U::Target: UtxoLookup,
- {
+ ) -> Result<(), LightningError> {
self.pre_channel_announcement_validation_check(&msg, utxo_lookup)?;
self.update_channel_from_unsigned_announcement_intern(msg, None, utxo_lookup)
}
@@ -2126,12 +2110,9 @@ impl<L: Logger> NetworkGraph<L> {
///
/// In those cases, this will return an `Err` that we can return immediately. Otherwise it will
/// return an `Ok(())`.
- fn pre_channel_announcement_validation_check<U: Deref>(
+ fn pre_channel_announcement_validation_check<U: UtxoLookup>(
&self, msg: &msgs::UnsignedChannelAnnouncement, utxo_lookup: &Option<U>,
- ) -> Result<(), LightningError>
- where
- U::Target: UtxoLookup,
- {
+ ) -> Result<(), LightningError> {
let channels = self.channels.read().unwrap();
if let Some(chan) = channels.get(&msg.short_channel_id) {
@@ -2170,13 +2151,10 @@ impl<L: Logger> NetworkGraph<L> {
///
/// Generally [`Self::pre_channel_announcement_validation_check`] should have been called
/// first.
- fn update_channel_from_unsigned_announcement_intern<U: Deref>(
+ fn update_channel_from_unsigned_announcement_intern<U: UtxoLookup>(
&self, msg: &msgs::UnsignedChannelAnnouncement,
full_msg: Option<&msgs::ChannelAnnouncement>, utxo_lookup: &Option<U>,
- ) -> Result<(), LightningError>
- where
- U::Target: UtxoLookup,
- {
+ ) -> Result<(), LightningError> {
if msg.node_id_1 == msg.node_id_2 || msg.bitcoin_key_1 == msg.bitcoin_key_2 {
return Err(LightningError {
err: "Channel announcement node had a channel with itself".to_owned(),
diff --git a/lightning/src/routing/utxo.rs b/lightning/src/routing/utxo.rs
index 089c536..466b941 100644
--- a/lightning/src/routing/utxo.rs
+++ b/lightning/src/routing/utxo.rs
@@ -75,6 +75,15 @@ pub trait UtxoLookup {
) -> UtxoResult;
}
+impl<T: UtxoLookup + ?Sized, U: Deref<Target = T>> UtxoLookup for U {
+ fn get_utxo(
+ &self, chain_hash: &ChainHash, short_channel_id: u64,
+ async_completion_notifier: Arc<Notifier>,
+ ) -> UtxoResult {
+ self.deref().get_utxo(chain_hash, short_channel_id, async_completion_notifier)
+ }
+}
+
enum ChannelAnnouncement {
Full(msgs::ChannelAnnouncement),
Unsigned(msgs::UnsignedChannelAnnouncement),
@@ -352,13 +361,10 @@ impl PendingChecks {
Ok(())
}
- pub(super) fn check_channel_announcement<U: Deref>(
+ pub(super) fn check_channel_announcement<U: UtxoLookup>(
&self, utxo_lookup: &Option<U>, msg: &msgs::UnsignedChannelAnnouncement,
full_msg: Option<&msgs::ChannelAnnouncement>,
- ) -> Result<Option<Amount>, msgs::LightningError>
- where
- U::Target: UtxoLookup,
- {
+ ) -> Result<Option<Amount>, msgs::LightningError> {
let handle_result = |res| match res {
Ok(TxOut { value, script_pubkey }) => {
let expected_script = make_funding_redeemscript_from_slices(
Why this scored 14/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.