Automatically update fees on outbound channels as fees change
[rust-lightning] / lightning-background-processor / src / lib.rs
index 5573b101ef7139bdb53ac6201d4b01c8b9cb07f5..4fdf2eeff03e298cc9dda25fb28739101f361fcf 100644 (file)
@@ -39,6 +39,7 @@ use std::ops::Deref;
 /// then there is a risk of channels force-closing on startup when the manager realizes it's
 /// outdated. However, as long as `ChannelMonitor` backups are sound, no funds besides those used
 /// for unilateral chain closure fees are at risk.
+#[must_use = "BackgroundProcessor will immediately stop on drop. It should be stored until shutdown."]
 pub struct BackgroundProcessor {
        stop_thread: Arc<AtomicBool>,
        thread_handle: Option<JoinHandle<Result<(), std::io::Error>>>,
@@ -139,6 +140,9 @@ impl BackgroundProcessor {
                let stop_thread = Arc::new(AtomicBool::new(false));
                let stop_thread_clone = stop_thread.clone();
                let handle = thread::spawn(move || -> Result<(), std::io::Error> {
+                       log_trace!(logger, "Calling ChannelManager's timer_tick_occurred on startup");
+                       channel_manager.timer_tick_occurred();
+
                        let mut last_freshness_call = Instant::now();
                        let mut last_ping_call = Instant::now();
                        loop {
@@ -160,7 +164,19 @@ impl BackgroundProcessor {
                                        channel_manager.timer_tick_occurred();
                                        last_freshness_call = Instant::now();
                                }
-                               if last_ping_call.elapsed().as_secs() > PING_TIMER {
+                               if last_ping_call.elapsed().as_secs() > PING_TIMER * 2 {
+                                       // On various platforms, we may be starved of CPU cycles for several reasons.
+                                       // E.g. on iOS, if we've been in the background, we will be entirely paused.
+                                       // Similarly, if we're on a desktop platform and the device has been asleep, we
+                                       // may not get any cycles.
+                                       // In any case, if we've been entirely paused for more than double our ping
+                                       // timer, we should have disconnected all sockets by now (and they're probably
+                                       // dead anyway), so disconnect them by calling `timer_tick_occurred()` twice.
+                                       log_trace!(logger, "Awoke after more than double our ping timer, disconnecting peers.");
+                                       peer_manager.timer_tick_occurred();
+                                       peer_manager.timer_tick_occurred();
+                                       last_ping_call = Instant::now();
+                               } else if last_ping_call.elapsed().as_secs() > PING_TIMER {
                                        log_trace!(logger, "Calling PeerManager's timer_tick_occurred");
                                        peer_manager.timer_tick_occurred();
                                        last_ping_call = Instant::now();
@@ -230,7 +246,7 @@ mod tests {
        use lightning::get_event_msg;
        use lightning::ln::channelmanager::{BREAKDOWN_TIMEOUT, ChainParameters, ChannelManager, SimpleArcChannelManager};
        use lightning::ln::features::InitFeatures;
-       use lightning::ln::msgs::ChannelMessageHandler;
+       use lightning::ln::msgs::{ChannelMessageHandler, Init};
        use lightning::ln::peer_handler::{PeerManager, MessageHandler, SocketDescriptor};
        use lightning::util::config::UserConfig;
        use lightning::util::events::{Event, MessageSendEventsProvider, MessageSendEvent};
@@ -304,6 +320,14 @@ mod tests {
                        let node = Node { node: manager, peer_manager, chain_monitor, persister, tx_broadcaster, logger, best_block };
                        nodes.push(node);
                }
+
+               for i in 0..num_nodes {
+                       for j in (i+1)..num_nodes {
+                               nodes[i].node.peer_connected(&nodes[j].node.get_our_node_id(), &Init { features: InitFeatures::known() });
+                               nodes[j].node.peer_connected(&nodes[i].node.get_our_node_id(), &Init { features: InitFeatures::known() });
+                       }
+               }
+
                nodes
        }