+ #[cfg(feature = "std")]
+ /// Removes information about channels that we haven't heard any updates about in some time.
+ /// This can be used regularly to prune the network graph of channels that likely no longer
+ /// exist.
+ ///
+ /// While there is no formal requirement that nodes regularly re-broadcast their channel
+ /// updates every two weeks, the non-normative section of BOLT 7 currently suggests that
+ /// pruning occur for updates which are at least two weeks old, which we implement here.
+ ///
+ /// Note that for users of the `lightning-background-processor` crate this method may be
+ /// automatically called regularly for you.
+ ///
+ /// This method is only available with the `std` feature. See
+ /// [`NetworkGraph::remove_stale_channels_with_time`] for `no-std` use.
+ pub fn remove_stale_channels(&self) {
+ let time = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time must be > 1970").as_secs();
+ self.remove_stale_channels_with_time(time);
+ }
+
+ /// Removes information about channels that we haven't heard any updates about in some time.
+ /// This can be used regularly to prune the network graph of channels that likely no longer
+ /// exist.
+ ///
+ /// While there is no formal requirement that nodes regularly re-broadcast their channel
+ /// updates every two weeks, the non-normative section of BOLT 7 currently suggests that
+ /// pruning occur for updates which are at least two weeks old, which we implement here.
+ ///
+ /// This function takes the current unix time as an argument. For users with the `std` feature
+ /// enabled, [`NetworkGraph::remove_stale_channels`] may be preferable.
+ pub fn remove_stale_channels_with_time(&self, current_time_unix: u64) {
+ let mut channels = self.channels.write().unwrap();
+ // Time out if we haven't received an update in at least 14 days.
+ if current_time_unix > u32::max_value() as u64 { return; } // Remove by 2106
+ if current_time_unix < STALE_CHANNEL_UPDATE_AGE_LIMIT_SECS { return; }
+ let min_time_unix: u32 = (current_time_unix - STALE_CHANNEL_UPDATE_AGE_LIMIT_SECS) as u32;
+ // Sadly BTreeMap::retain was only stabilized in 1.53 so we can't switch to it for some
+ // time.
+ let mut scids_to_remove = Vec::new();
+ for (scid, info) in channels.iter_mut() {
+ if info.one_to_two.is_some() && info.one_to_two.as_ref().unwrap().last_update < min_time_unix {
+ info.one_to_two = None;
+ }
+ if info.two_to_one.is_some() && info.two_to_one.as_ref().unwrap().last_update < min_time_unix {
+ info.two_to_one = None;
+ }
+ if info.one_to_two.is_none() && info.two_to_one.is_none() {
+ // We check the announcement_received_time here to ensure we don't drop
+ // announcements that we just received and are just waiting for our peer to send a
+ // channel_update for.
+ if info.announcement_received_time < min_time_unix as u64 {
+ scids_to_remove.push(*scid);
+ }
+ }
+ }
+ if !scids_to_remove.is_empty() {
+ let mut nodes = self.nodes.write().unwrap();
+ for scid in scids_to_remove {
+ let info = channels.remove(&scid).expect("We just accessed this scid, it should be present");
+ Self::remove_channel_in_nodes(&mut nodes, &info, scid);
+ }
+ }
+ }
+