Merge pull request #1031 from p2pderivatives/dlc-version-generic
[rust-lightning] / lightning-background-processor / src / lib.rs
index 5573b101ef7139bdb53ac6201d4b01c8b9cb07f5..34cddd1a6aa8b83ea36699e0bb39c4a21b97480a 100644 (file)
@@ -16,6 +16,7 @@ use lightning::chain::keysinterface::{Sign, KeysInterface};
 use lightning::ln::channelmanager::ChannelManager;
 use lightning::ln::msgs::{ChannelMessageHandler, RoutingMessageHandler};
 use lightning::ln::peer_handler::{PeerManager, SocketDescriptor};
+use lightning::ln::peer_handler::CustomMessageHandler;
 use lightning::util::events::{EventHandler, EventsProvider};
 use lightning::util::logger::Logger;
 use std::sync::Arc;
@@ -39,6 +40,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>>>,
@@ -49,7 +51,13 @@ const FRESHNESS_TIMER: u64 = 60;
 #[cfg(test)]
 const FRESHNESS_TIMER: u64 = 1;
 
+#[cfg(not(debug_assertions))]
 const PING_TIMER: u64 = 5;
+/// Signature operations take a lot longer without compiler optimisations.
+/// Increasing the ping timer allows for this but slower devices will be disconnected if the
+/// timeout is reached.
+#[cfg(debug_assertions)]
+const PING_TIMER: u64 = 30;
 
 /// Trait which handles persisting a [`ChannelManager`] to disk.
 ///
@@ -122,7 +130,8 @@ impl BackgroundProcessor {
                CMP: 'static + Send + ChannelManagerPersister<Signer, CW, T, K, F, L>,
                M: 'static + Deref<Target = ChainMonitor<Signer, CF, T, F, L, P>> + Send + Sync,
                CM: 'static + Deref<Target = ChannelManager<Signer, CW, T, K, F, L>> + Send + Sync,
-               PM: 'static + Deref<Target = PeerManager<Descriptor, CMH, RMH, L>> + Send + Sync,
+               UMH: 'static + Deref + Send + Sync,
+               PM: 'static + Deref<Target = PeerManager<Descriptor, CMH, RMH, L, UMH>> + Send + Sync,
        >
        (persister: CMP, event_handler: EH, chain_monitor: M, channel_manager: CM, peer_manager: PM, logger: L) -> Self
        where
@@ -135,10 +144,14 @@ impl BackgroundProcessor {
                P::Target: 'static + channelmonitor::Persist<Signer>,
                CMH::Target: 'static + ChannelMessageHandler,
                RMH::Target: 'static + RoutingMessageHandler,
+               UMH::Target: 'static + CustomMessageHandler,
        {
                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 +173,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,8 +255,8 @@ 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::peer_handler::{PeerManager, MessageHandler, SocketDescriptor};
+       use lightning::ln::msgs::{ChannelMessageHandler, Init};
+       use lightning::ln::peer_handler::{PeerManager, MessageHandler, SocketDescriptor, IgnoringMessageHandler};
        use lightning::util::config::UserConfig;
        use lightning::util::events::{Event, MessageSendEventsProvider, MessageSendEvent};
        use lightning::util::ser::Writeable;
@@ -259,7 +284,7 @@ mod tests {
 
        struct Node {
                node: Arc<SimpleArcChannelManager<ChainMonitor, test_utils::TestBroadcaster, test_utils::TestFeeEstimator, test_utils::TestLogger>>,
-               peer_manager: Arc<PeerManager<TestDescriptor, Arc<test_utils::TestChannelMessageHandler>, Arc<test_utils::TestRoutingMessageHandler>, Arc<test_utils::TestLogger>>>,
+               peer_manager: Arc<PeerManager<TestDescriptor, Arc<test_utils::TestChannelMessageHandler>, Arc<test_utils::TestRoutingMessageHandler>, Arc<test_utils::TestLogger>, IgnoringMessageHandler>>,
                chain_monitor: Arc<ChainMonitor>,
                persister: Arc<FilesystemPersister>,
                tx_broadcaster: Arc<test_utils::TestBroadcaster>,
@@ -300,10 +325,18 @@ mod tests {
                        let params = ChainParameters { network, best_block };
                        let manager = Arc::new(ChannelManager::new(fee_estimator.clone(), chain_monitor.clone(), tx_broadcaster.clone(), logger.clone(), keys_manager.clone(), UserConfig::default(), params));
                        let msg_handler = MessageHandler { chan_handler: Arc::new(test_utils::TestChannelMessageHandler::new()), route_handler: Arc::new(test_utils::TestRoutingMessageHandler::new() )};
-                       let peer_manager = Arc::new(PeerManager::new(msg_handler, keys_manager.get_node_secret(), &seed, logger.clone()));
+                       let peer_manager = Arc::new(PeerManager::new(msg_handler, keys_manager.get_node_secret(), &seed, logger.clone(), IgnoringMessageHandler{}));
                        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
        }