From 4800a473efb97762481a2d558b8fce2cc41cf0f9 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 2 Feb 2026 15:32:07 +0100 Subject: [PATCH] Add AChainMonitor trait and use it in background processor Add a new `AChainMonitor` trait following the same pattern as `AChannelManager`. This trait provides associated types for all generic parameters of `ChainMonitor` and a `get_cm()` method to access the underlying `ChainMonitor`. Update the background processor to use `AChainMonitor` trait bounds instead of spelling out the full `ChainMonitor` generic parameters. This simplifies the function signatures by removing 5-6 explicit generic parameters (CF, T, F, P, ES) per function. This is preparation for adding a flush method to the AChainMonitor trait. Co-Authored-By: Claude Opus 4.5 --- lightning-background-processor/src/lib.rs | 101 +++++++++++++--------- lightning/src/chain/chainmonitor.rs | 60 +++++++++++++ 2 files changed, 118 insertions(+), 43 deletions(-) diff --git a/lightning-background-processor/src/lib.rs b/lightning-background-processor/src/lib.rs index 26e8fc64a42..bb99d65e6b5 100644 --- a/lightning-background-processor/src/lib.rs +++ b/lightning-background-processor/src/lib.rs @@ -30,9 +30,11 @@ mod fwd_batch; use fwd_batch::BatchDelay; +#[cfg(not(c_bindings))] use lightning::chain; +#[cfg(not(c_bindings))] use lightning::chain::chaininterface::{BroadcasterInterface, FeeEstimator}; -use lightning::chain::chainmonitor::{ChainMonitor, Persist}; +use lightning::chain::chainmonitor::AChainMonitor; #[cfg(feature = "std")] use lightning::events::EventHandler; #[cfg(feature = "std")] @@ -50,9 +52,9 @@ use lightning::onion_message::messenger::AOnionMessenger; use lightning::routing::gossip::{NetworkGraph, P2PGossipSync}; use lightning::routing::scoring::{ScoreUpdate, WriteableScore}; use lightning::routing::utxo::UtxoLookup; -use lightning::sign::{ - ChangeDestinationSource, ChangeDestinationSourceSync, EntropySource, OutputSpender, -}; +#[cfg(not(c_bindings))] +use lightning::sign::EntropySource; +use lightning::sign::{ChangeDestinationSource, ChangeDestinationSourceSync, OutputSpender}; #[cfg(not(c_bindings))] use lightning::util::async_poll::MaybeSend; use lightning::util::logger::Logger; @@ -118,6 +120,7 @@ use alloc::vec::Vec; /// /// [`ChannelManager`]: lightning::ln::channelmanager::ChannelManager /// [`ChannelManager::timer_tick_occurred`]: lightning::ln::channelmanager::ChannelManager::timer_tick_occurred +/// [`ChainMonitor::rebroadcast_pending_claims`]: lightning::chain::chainmonitor::ChainMonitor::rebroadcast_pending_claims /// [`ChannelMonitor`]: lightning::chain::channelmonitor::ChannelMonitor /// [`Event`]: lightning::events::Event /// [`PeerManager::timer_tick_occurred`]: lightning::ln::peer_handler::PeerManager::timer_tick_occurred @@ -923,16 +926,11 @@ use futures_util::{dummy_waker, Joiner, OptionalSelector, Selector, SelectorOutp pub async fn process_events_async< 'a, UL: UtxoLookup, - CF: chain::Filter, - T: BroadcasterInterface, - F: FeeEstimator, G: Deref>, L: Logger, - P: Deref, EventHandlerFuture: core::future::Future>, EventHandler: Fn(Event) -> EventHandlerFuture, - ES: EntropySource, - M: Deref::Signer, CF, T, F, L, P, ES>>, + M: Deref, CM: Deref, OM: Deref, PGS: Deref>, @@ -942,7 +940,17 @@ pub async fn process_events_async< D: Deref, O: OutputSpender, K: KVStore, - OS: Deref>, + OS: Deref< + Target = OutputSweeper< + ::Broadcaster, + D, + ::FeeEstimator, + ::Filter, + K, + L, + O, + >, + >, S: Deref, SC: for<'b> WriteableScore<'b>, SleepFuture: core::future::Future + core::marker::Unpin, @@ -955,7 +963,7 @@ pub async fn process_events_async< sleeper: Sleeper, mobile_interruptable_platform: bool, fetch_time: FetchTime, ) -> Result<(), lightning::io::Error> where - P::Target: Persist<::Signer>, + M::Target: AChainMonitor::Signer, Logger = L>, CM::Target: AChannelManager, OM::Target: AOnionMessenger, PM::Target: APeerManager, @@ -1004,7 +1012,7 @@ where log_trace!(logger, "Calling ChannelManager's timer_tick_occurred on startup"); channel_manager.get_cm().timer_tick_occurred(); log_trace!(logger, "Rebroadcasting monitor's pending claims on startup"); - chain_monitor.rebroadcast_pending_claims(); + chain_monitor.get_cm().rebroadcast_pending_claims(); let mut last_freshness_call = sleeper(FRESHNESS_TIMER); let mut last_onion_message_handler_call = sleeper(ONION_MESSAGE_HANDLER_TIMER); @@ -1022,7 +1030,7 @@ where loop { channel_manager.get_cm().process_pending_events_async(async_event_handler).await; - chain_monitor.process_pending_events_async(async_event_handler).await; + chain_monitor.get_cm().process_pending_events_async(async_event_handler).await; if let Some(om) = &onion_messenger { om.get_om().process_pending_events_async(async_event_handler).await } @@ -1072,7 +1080,7 @@ where let fut = Selector { a: sleeper(sleep_delay), b: channel_manager.get_cm().get_event_or_persistence_needed_future(), - c: chain_monitor.get_update_future(), + c: chain_monitor.get_cm().get_update_future(), d: om_fut, e: lm_fut, f: gv_fut, @@ -1164,7 +1172,7 @@ where }; if archive_timer_elapsed { log_trace!(logger, "Archiving stale ChannelMonitors."); - chain_monitor.archive_fully_resolved_channel_monitors(); + chain_monitor.get_cm().archive_fully_resolved_channel_monitors(); have_archived = true; log_trace!(logger, "Archived stale ChannelMonitors."); } @@ -1354,7 +1362,7 @@ where match check_and_reset_sleeper(&mut last_rebroadcast_call, || sleeper(REBROADCAST_TIMER)) { Some(false) => { log_trace!(logger, "Rebroadcasting monitor's pending claims"); - chain_monitor.rebroadcast_pending_claims(); + chain_monitor.get_cm().rebroadcast_pending_claims(); }, Some(true) => break, None => {}, @@ -1416,16 +1424,11 @@ fn check_and_reset_sleeper< /// synchronous background persistence. pub async fn process_events_async_with_kv_store_sync< UL: UtxoLookup, - CF: chain::Filter, - T: BroadcasterInterface, - F: FeeEstimator, G: Deref>, L: Logger, - P: Deref, EventHandlerFuture: core::future::Future>, EventHandler: Fn(Event) -> EventHandlerFuture, - ES: EntropySource, - M: Deref::Signer, CF, T, F, L, P, ES>>, + M: Deref, CM: Deref, OM: Deref, PGS: Deref>, @@ -1435,7 +1438,17 @@ pub async fn process_events_async_with_kv_store_sync< D: Deref, O: OutputSpender, K: Deref, - OS: Deref>, + OS: Deref< + Target = OutputSweeperSync< + ::Broadcaster, + D, + ::FeeEstimator, + ::Filter, + K, + L, + O, + >, + >, S: Deref, SC: for<'b> WriteableScore<'b>, SleepFuture: core::future::Future + core::marker::Unpin, @@ -1448,7 +1461,7 @@ pub async fn process_events_async_with_kv_store_sync< sleeper: Sleeper, mobile_interruptable_platform: bool, fetch_time: FetchTime, ) -> Result<(), lightning::io::Error> where - P::Target: Persist<::Signer>, + M::Target: AChainMonitor::Signer, Logger = L>, CM::Target: AChannelManager, OM::Target: AOnionMessenger, PM::Target: APeerManager, @@ -1523,20 +1536,10 @@ impl BackgroundProcessor { pub fn start< 'a, UL: 'static + UtxoLookup, - CF: 'static + chain::Filter, - T: 'static + BroadcasterInterface, - F: 'static + FeeEstimator + Send, G: 'static + Deref>, L: 'static + Deref + Send, - P: 'static + Deref, EH: 'static + EventHandler + Send, - ES: 'static + EntropySource + Send, - M: 'static - + Deref< - Target = ChainMonitor<::Signer, CF, T, F, L, P, ES>, - > - + Send - + Sync, + M: 'static + Deref + Send + Sync, CM: 'static + Deref + Send, OM: 'static + Deref + Send, PGS: 'static + Deref> + Send, @@ -1548,7 +1551,19 @@ impl BackgroundProcessor { D: 'static + Deref, O: 'static + OutputSpender, K: 'static + Deref + Send, - OS: 'static + Deref> + Send, + OS: 'static + + Deref< + Target = OutputSweeperSync< + ::Broadcaster, + D, + ::FeeEstimator, + ::Filter, + K, + L, + O, + >, + > + + Send, >( kv_store: K, event_handler: EH, chain_monitor: M, channel_manager: CM, onion_messenger: Option, gossip_sync: GossipSync, peer_manager: PM, @@ -1556,7 +1571,7 @@ impl BackgroundProcessor { ) -> Self where L::Target: 'static + Logger, - P::Target: 'static + Persist<::Signer>, + M::Target: AChainMonitor::Signer, Logger = L>, CM::Target: AChannelManager, OM::Target: AOnionMessenger, PM::Target: APeerManager, @@ -1596,7 +1611,7 @@ impl BackgroundProcessor { log_trace!(logger, "Calling ChannelManager's timer_tick_occurred on startup"); channel_manager.get_cm().timer_tick_occurred(); log_trace!(logger, "Rebroadcasting monitor's pending claims on startup"); - chain_monitor.rebroadcast_pending_claims(); + chain_monitor.get_cm().rebroadcast_pending_claims(); let mut last_freshness_call = Instant::now(); let mut last_onion_message_handler_call = Instant::now(); @@ -1615,7 +1630,7 @@ impl BackgroundProcessor { loop { channel_manager.get_cm().process_pending_events(&event_handler); - chain_monitor.process_pending_events(&event_handler); + chain_monitor.get_cm().process_pending_events(&event_handler); if let Some(om) = &onion_messenger { om.get_om().process_pending_events(&event_handler) }; @@ -1648,7 +1663,7 @@ impl BackgroundProcessor { let gv_fut = gossip_sync.validation_completion_future(); let always_futures = [ channel_manager.get_cm().get_event_or_persistence_needed_future(), - chain_monitor.get_update_future(), + chain_monitor.get_cm().get_update_future(), ]; let futures = always_futures.into_iter().chain(om_fut).chain(lm_fut).chain(gv_fut); let sleeper = Sleeper::from_futures(futures); @@ -1701,7 +1716,7 @@ impl BackgroundProcessor { let archive_timer_elapsed = last_archive_call.elapsed() > archive_timer; if archive_timer_elapsed { log_trace!(logger, "Archiving stale ChannelMonitors."); - chain_monitor.archive_fully_resolved_channel_monitors(); + chain_monitor.get_cm().archive_fully_resolved_channel_monitors(); have_archived = true; last_archive_call = Instant::now(); log_trace!(logger, "Archived stale ChannelMonitors."); @@ -1786,7 +1801,7 @@ impl BackgroundProcessor { } if last_rebroadcast_call.elapsed() > REBROADCAST_TIMER { log_trace!(logger, "Rebroadcasting monitor's pending claims"); - chain_monitor.rebroadcast_pending_claims(); + chain_monitor.get_cm().rebroadcast_pending_claims(); last_rebroadcast_call = Instant::now(); } } diff --git a/lightning/src/chain/chainmonitor.rs b/lightning/src/chain/chainmonitor.rs index 2db34738737..17693f8ca7a 100644 --- a/lightning/src/chain/chainmonitor.rs +++ b/lightning/src/chain/chainmonitor.rs @@ -1488,6 +1488,66 @@ where } } +/// A trivial trait which describes any [`ChainMonitor`]. +/// +/// This is not exported to bindings users as general cover traits aren't useful in other +/// languages. +pub trait AChainMonitor { + /// A type implementing [`EcdsaChannelSigner`]. + type Signer: EcdsaChannelSigner + Sized; + /// A type implementing [`chain::Filter`]. + type Filter: chain::Filter; + /// A type implementing [`BroadcasterInterface`]. + type Broadcaster: BroadcasterInterface; + /// A type implementing [`FeeEstimator`]. + type FeeEstimator: FeeEstimator; + /// A type implementing [`Logger`]. + type Logger: Logger; + /// A type that derefs to [`Persist`]. + type Persister: Deref; + /// The target of [`Self::Persister`]. + type PersisterTarget: Persist + ?Sized; + /// A type implementing [`EntropySource`]. + type EntropySource: EntropySource; + /// Returns a reference to the actual [`ChainMonitor`] object. + fn get_cm( + &self, + ) -> &ChainMonitor< + Self::Signer, + Self::Filter, + Self::Broadcaster, + Self::FeeEstimator, + Self::Logger, + Self::Persister, + Self::EntropySource, + >; +} + +impl< + ChannelSigner: EcdsaChannelSigner, + C: chain::Filter, + T: BroadcasterInterface, + F: FeeEstimator, + L: Logger, + P: Deref, + ES: EntropySource, + > AChainMonitor for ChainMonitor +where + P::Target: Persist, +{ + type Signer = ChannelSigner; + type Filter = C; + type Broadcaster = T; + type FeeEstimator = F; + type Logger = L; + type Persister = P; + type PersisterTarget = P::Target; + type EntropySource = ES; + fn get_cm(&self) -> &ChainMonitor { + self + } +} + #[cfg(test)] mod tests { use crate::chain::channelmonitor::ANTI_REORG_DELAY;