Drop Deref indirection for chain::Watch
What changed, and why it matters
This is a routine internal refactoring in a Rust Lightning library. It removes an extra layer of pointer-like indirection (the Deref trait) from how the chain watcher type is used, replacing it with a blanket implementation so the same types still work. The commit explicitly states the goal is to reduce generics and verbosity while keeping behavior equivalent. There is no security fix, bug patch, or externally reported issue.
No security action needed. Treat as normal code-quality refactoring; review only for compilation and API compatibility in downstream consumers.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch refactors the chain::Watch integration in ChannelManager and related types. Previously, ChannelManager<M: Deref> required M::Target: chain::Watch. The change adds a blanket impl<...> Watch<ChannelSigner> for W where W: Deref<Target = T>, T: Watch<ChannelSigner> in lightning/src/chain/mod.rs, then changes ChannelManager and AChannelManager to require M: chain::Watch<SP::EcdsaSigner> directly and removes the M::Target associated type. This is a type-system simplification; runtime behavior is unchanged because the blanket impl forwards each Watch method through Deref exactly as before.
Changed components
lightning/src/chain/mod.rslightning/src/ln/channelmanager.rslightning/src/ln/functional_test_utils.rsInspect captured patch +50 / −67
diff --git a/lightning/src/chain/mod.rs b/lightning/src/chain/mod.rs
index b4cc6a3..9f5c965 100644
--- a/lightning/src/chain/mod.rs
+++ b/lightning/src/chain/mod.rs
@@ -25,6 +25,8 @@ use crate::ln::types::ChannelId;
use crate::sign::ecdsa::EcdsaChannelSigner;
use crate::sign::HTLCDescriptor;
+use core::ops::Deref;
+
#[allow(unused_imports)]
use crate::prelude::*;
@@ -346,6 +348,28 @@ pub trait Watch<ChannelSigner: EcdsaChannelSigner> {
) -> Vec<(OutPoint, ChannelId, Vec<MonitorEvent>, PublicKey)>;
}
+impl<ChannelSigner: EcdsaChannelSigner, T: Watch<ChannelSigner> + ?Sized, W: Deref<Target = T>>
+ Watch<ChannelSigner> for W
+{
+ fn watch_channel(
+ &self, channel_id: ChannelId, monitor: ChannelMonitor<ChannelSigner>,
+ ) -> Result<ChannelMonitorUpdateStatus, ()> {
+ self.deref().watch_channel(channel_id, monitor)
+ }
+
+ fn update_channel(
+ &self, channel_id: ChannelId, update: &ChannelMonitorUpdate,
+ ) -> ChannelMonitorUpdateStatus {
+ self.deref().update_channel(channel_id, update)
+ }
+
+ fn release_pending_monitor_events(
+ &self,
+ ) -> Vec<(OutPoint, ChannelId, Vec<MonitorEvent>, PublicKey)> {
+ self.deref().release_pending_monitor_events()
+ }
+}
+
/// The `Filter` trait defines behavior for indicating chain activity of interest pertaining to
/// channels.
///
diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs
index cd61a59..440ca34 100644
--- a/lightning/src/ln/channelmanager.rs
+++ b/lightning/src/ln/channelmanager.rs
@@ -1777,9 +1777,7 @@ pub type SimpleRefChannelManager<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, M, T, F, L>
/// languages.
pub trait AChannelManager {
/// A type implementing [`chain::Watch`].
- type Watch: chain::Watch<Self::Signer> + ?Sized;
- /// A type that may be dereferenced to [`Self::Watch`].
- type M: Deref<Target = Self::Watch>;
+ type Watch: chain::Watch<Self::Signer>;
/// A type implementing [`BroadcasterInterface`].
type Broadcaster: BroadcasterInterface;
/// A type implementing [`EntropySource`].
@@ -1802,7 +1800,7 @@ pub trait AChannelManager {
fn get_cm(
&self,
) -> &ChannelManager<
- Self::M,
+ Self::Watch,
Self::Broadcaster,
Self::EntropySource,
Self::NodeSigner,
@@ -1815,7 +1813,7 @@ pub trait AChannelManager {
}
impl<
- M: Deref,
+ M: chain::Watch<SP::EcdsaSigner>,
T: BroadcasterInterface,
ES: EntropySource,
NS: NodeSigner,
@@ -1825,11 +1823,8 @@ impl<
MR: MessageRouter,
L: Logger,
> AChannelManager for ChannelManager<M, T, ES, NS, SP, F, R, MR, L>
-where
- M::Target: chain::Watch<SP::EcdsaSigner>,
{
- type Watch = M::Target;
- type M = M;
+ type Watch = M;
type Broadcaster = T;
type EntropySource = ES;
type NodeSigner = NS;
@@ -2584,7 +2579,7 @@ where
/// [`ChannelUpdate`]: msgs::ChannelUpdate
/// [`read`]: ReadableArgs::read
pub struct ChannelManager<
- M: Deref,
+ M: chain::Watch<SP::EcdsaSigner>,
T: BroadcasterInterface,
ES: EntropySource,
NS: NodeSigner,
@@ -2593,9 +2588,7 @@ pub struct ChannelManager<
R: Router,
MR: MessageRouter,
L: Logger,
-> where
- M::Target: chain::Watch<SP::EcdsaSigner>,
-{
+> {
config: RwLock<UserConfig>,
chain_hash: ChainHash,
fee_estimator: LowerBoundedFeeEstimator<F>,
@@ -3366,7 +3359,7 @@ fn create_htlc_intercepted_event(
}
impl<
- M: Deref,
+ M: chain::Watch<SP::EcdsaSigner>,
T: BroadcasterInterface,
ES: EntropySource,
NS: NodeSigner,
@@ -3376,8 +3369,6 @@ impl<
MR: MessageRouter,
L: Logger,
> ChannelManager<M, T, ES, NS, SP, F, R, MR, L>
-where
- M::Target: chain::Watch<SP::EcdsaSigner>,
{
/// Constructs a new `ChannelManager` to hold several channels and route between them.
///
@@ -13490,7 +13481,7 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => {
} }
impl<
- M: Deref,
+ M: Watch<SP::EcdsaSigner>,
T: BroadcasterInterface,
ES: EntropySource,
NS: NodeSigner,
@@ -13500,8 +13491,6 @@ impl<
MR: MessageRouter,
L: Logger,
> ChannelManager<M, T, ES, NS, SP, F, R, MR, L>
-where
- M::Target: chain::Watch<SP::EcdsaSigner>,
{
#[cfg(not(c_bindings))]
create_offer_builder!(self, OfferBuilder<'_, DerivedMetadata, secp256k1::All>);
@@ -14359,7 +14348,7 @@ where
}
impl<
- M: Deref,
+ M: chain::Watch<SP::EcdsaSigner>,
T: BroadcasterInterface,
ES: EntropySource,
NS: NodeSigner,
@@ -14369,8 +14358,6 @@ impl<
MR: MessageRouter,
L: Logger,
> BaseMessageHandler for ChannelManager<M, T, ES, NS, SP, F, R, MR, L>
-where
- M::Target: chain::Watch<SP::EcdsaSigner>,
{
fn provided_node_features(&self) -> NodeFeatures {
provided_node_features(&self.config.read().unwrap())
@@ -14722,7 +14709,7 @@ where
}
impl<
- M: Deref,
+ M: chain::Watch<SP::EcdsaSigner>,
T: BroadcasterInterface,
ES: EntropySource,
NS: NodeSigner,
@@ -14732,8 +14719,6 @@ impl<
MR: MessageRouter,
L: Logger,
> EventsProvider for ChannelManager<M, T, ES, NS, SP, F, R, MR, L>
-where
- M::Target: chain::Watch<SP::EcdsaSigner>,
{
/// Processes events that must be periodically handled.
///
@@ -14749,7 +14734,7 @@ where
}
impl<
- M: Deref,
+ M: chain::Watch<SP::EcdsaSigner>,
T: BroadcasterInterface,
ES: EntropySource,
NS: NodeSigner,
@@ -14759,8 +14744,6 @@ impl<
MR: MessageRouter,
L: Logger,
> chain::Listen for ChannelManager<M, T, ES, NS, SP, F, R, MR, L>
-where
- M::Target: chain::Watch<SP::EcdsaSigner>,
{
fn filtered_block_connected(&self, header: &Header, txdata: &TransactionData, height: u32) {
{
@@ -14802,7 +14785,7 @@ where
}
impl<
- M: Deref,
+ M: chain::Watch<SP::EcdsaSigner>,
T: BroadcasterInterface,
ES: EntropySource,
NS: NodeSigner,
@@ -14812,8 +14795,6 @@ impl<
MR: MessageRouter,
L: Logger,
> chain::Confirm for ChannelManager<M, T, ES, NS, SP, F, R, MR, L>
-where
- M::Target: chain::Watch<SP::EcdsaSigner>,
{
#[rustfmt::skip]
fn transactions_confirmed(&self, header: &Header, txdata: &TransactionData, height: u32) {
@@ -14967,7 +14948,7 @@ pub(super) enum FundingConfirmedMessage {
}
impl<
- M: Deref,
+ M: chain::Watch<SP::EcdsaSigner>,
T: BroadcasterInterface,
ES: EntropySource,
NS: NodeSigner,
@@ -14977,8 +14958,6 @@ impl<
MR: MessageRouter,
L: Logger,
> ChannelManager<M, T, ES, NS, SP, F, R, MR, L>
-where
- M::Target: chain::Watch<SP::EcdsaSigner>,
{
/// Calls a function which handles an on-chain event (blocks dis/connected, transactions
/// un/confirmed, etc) on each channel, handling any resulting errors or messages generated by
@@ -15321,7 +15300,7 @@ where
}
impl<
- M: Deref,
+ M: chain::Watch<SP::EcdsaSigner>,
T: BroadcasterInterface,
ES: EntropySource,
NS: NodeSigner,
@@ -15331,8 +15310,6 @@ impl<
MR: MessageRouter,
L: Logger,
> ChannelMessageHandler for ChannelManager<M, T, ES, NS, SP, F, R, MR, L>
-where
- M::Target: chain::Watch<SP::EcdsaSigner>,
{
fn handle_open_channel(&self, counterparty_node_id: PublicKey, message: &msgs::OpenChannel) {
// Note that we never need to persist the updated ChannelManager for an inbound
@@ -15888,7 +15865,7 @@ where
}
impl<
- M: Deref,
+ M: chain::Watch<SP::EcdsaSigner>,
T: BroadcasterInterface,
ES: EntropySource,
NS: NodeSigner,
@@ -15898,8 +15875,6 @@ impl<
MR: MessageRouter,
L: Logger,
> OffersMessageHandler for ChannelManager<M, T, ES, NS, SP, F, R, MR, L>
-where
- M::Target: chain::Watch<SP::EcdsaSigner>,
{
#[rustfmt::skip]
fn handle_message(
@@ -16098,7 +16073,7 @@ where
}
impl<
- M: Deref,
+ M: chain::Watch<SP::EcdsaSigner>,
T: BroadcasterInterface,
ES: EntropySource,
NS: NodeSigner,
@@ -16108,8 +16083,6 @@ impl<
MR: MessageRouter,
L: Logger,
> AsyncPaymentsMessageHandler for ChannelManager<M, T, ES, NS, SP, F, R, MR, L>
-where
- M::Target: chain::Watch<SP::EcdsaSigner>,
{
fn handle_offer_paths_request(
&self, message: OfferPathsRequest, context: AsyncPaymentsContext,
@@ -16335,7 +16308,7 @@ where
#[cfg(feature = "dnssec")]
impl<
- M: Deref,
+ M: chain::Watch<SP::EcdsaSigner>,
T: BroadcasterInterface,
ES: EntropySource,
NS: NodeSigner,
@@ -16345,8 +16318,6 @@ impl<
MR: MessageRouter,
L: Logger,
> DNSResolverMessageHandler for ChannelManager<M, T, ES, NS, SP, F, R, MR, L>
-where
- M::Target: chain::Watch<SP::EcdsaSigner>,
{
fn handle_dnssec_query(
&self, _message: DNSSECQuery, _responder: Option<Responder>,
@@ -16395,7 +16366,7 @@ where
}
impl<
- M: Deref,
+ M: chain::Watch<SP::EcdsaSigner>,
T: BroadcasterInterface,
ES: EntropySource,
NS: NodeSigner,
@@ -16405,8 +16376,6 @@ impl<
MR: MessageRouter,
L: Logger,
> NodeIdLookUp for ChannelManager<M, T, ES, NS, SP, F, R, MR, L>
-where
- M::Target: chain::Watch<SP::EcdsaSigner>,
{
fn next_node_id(&self, short_channel_id: u64) -> Option<PublicKey> {
self.short_to_chan_info.read().unwrap().get(&short_channel_id).map(|(pubkey, _)| *pubkey)
@@ -16903,7 +16872,7 @@ impl_writeable_tlv_based!(PendingInboundPayment, {
});
impl<
- M: Deref,
+ M: chain::Watch<SP::EcdsaSigner>,
T: BroadcasterInterface,
ES: EntropySource,
NS: NodeSigner,
@@ -16913,8 +16882,6 @@ impl<
MR: MessageRouter,
L: Logger,
> Writeable for ChannelManager<M, T, ES, NS, SP, F, R, MR, L>
-where
- M::Target: chain::Watch<SP::EcdsaSigner>,
{
#[rustfmt::skip]
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
@@ -17262,7 +17229,7 @@ impl Readable for VecDeque<(Event, Option<EventCompletionAction>)> {
/// [`ChainMonitor::load_existing_monitor`]: crate::chain::chainmonitor::ChainMonitor::load_existing_monitor
pub struct ChannelManagerReadArgs<
'a,
- M: Deref,
+ M: chain::Watch<SP::EcdsaSigner>,
T: BroadcasterInterface,
ES: EntropySource,
NS: NodeSigner,
@@ -17271,9 +17238,7 @@ pub struct ChannelManagerReadArgs<
R: Router,
MR: MessageRouter,
L: Logger + Clone,
-> where
- M::Target: chain::Watch<SP::EcdsaSigner>,
-{
+> {
/// A cryptographically secure source of entropy.
pub entropy_source: ES,
@@ -17333,7 +17298,7 @@ pub struct ChannelManagerReadArgs<
impl<
'a,
- M: Deref,
+ M: chain::Watch<SP::EcdsaSigner>,
T: BroadcasterInterface,
ES: EntropySource,
NS: NodeSigner,
@@ -17343,8 +17308,6 @@ impl<
MR: MessageRouter,
L: Logger + Clone,
> ChannelManagerReadArgs<'a, M, T, ES, NS, SP, F, R, MR, L>
-where
- M::Target: chain::Watch<SP::EcdsaSigner>,
{
/// Simple utility function to create a ChannelManagerReadArgs which creates the monitor
/// HashMap for you. This is primarily useful for C bindings where it is not practical to
@@ -17410,7 +17373,7 @@ fn dedup_decode_update_add_htlcs<L: Logger>(
// SipmleArcChannelManager type:
impl<
'a,
- M: Deref,
+ M: chain::Watch<SP::EcdsaSigner>,
T: BroadcasterInterface,
ES: EntropySource,
NS: NodeSigner,
@@ -17421,8 +17384,6 @@ impl<
L: Logger + Clone,
> ReadableArgs<ChannelManagerReadArgs<'a, M, T, ES, NS, SP, F, R, MR, L>>
for (BlockHash, Arc<ChannelManager<M, T, ES, NS, SP, F, R, MR, L>>)
-where
- M::Target: chain::Watch<SP::EcdsaSigner>,
{
fn read<Reader: io::Read>(
reader: &mut Reader, args: ChannelManagerReadArgs<'a, M, T, ES, NS, SP, F, R, MR, L>,
@@ -17435,7 +17396,7 @@ where
impl<
'a,
- M: Deref,
+ M: chain::Watch<SP::EcdsaSigner>,
T: BroadcasterInterface,
ES: EntropySource,
NS: NodeSigner,
@@ -17446,8 +17407,6 @@ impl<
L: Logger + Clone,
> ReadableArgs<ChannelManagerReadArgs<'a, M, T, ES, NS, SP, F, R, MR, L>>
for (BlockHash, ChannelManager<M, T, ES, NS, SP, F, R, MR, L>)
-where
- M::Target: chain::Watch<SP::EcdsaSigner>,
{
fn read<Reader: io::Read>(
reader: &mut Reader, mut args: ChannelManagerReadArgs<'a, M, T, ES, NS, SP, F, R, MR, L>,
diff --git a/lightning/src/ln/functional_test_utils.rs b/lightning/src/ln/functional_test_utils.rs
index bc75407..cea9ea4 100644
--- a/lightning/src/ln/functional_test_utils.rs
+++ b/lightning/src/ln/functional_test_utils.rs
@@ -732,7 +732,7 @@ pub trait NodeHolder {
fn node(
&self,
) -> &ChannelManager<
- <Self::CM as AChannelManager>::M,
+ <Self::CM as AChannelManager>::Watch,
<Self::CM as AChannelManager>::Broadcaster,
<Self::CM as AChannelManager>::EntropySource,
<Self::CM as AChannelManager>::NodeSigner,
@@ -749,7 +749,7 @@ impl<H: NodeHolder> NodeHolder for &H {
fn node(
&self,
) -> &ChannelManager<
- <Self::CM as AChannelManager>::M,
+ <Self::CM as AChannelManager>::Watch,
<Self::CM as AChannelManager>::Broadcaster,
<Self::CM as AChannelManager>::EntropySource,
<Self::CM as AChannelManager>::NodeSigner,
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.