Reject channel_update messages with timestamps too old or new
authorMatt Corallo <git@bluematt.me>
Tue, 14 Dec 2021 01:33:37 +0000 (01:33 +0000)
committerMatt Corallo <git@bluematt.me>
Thu, 16 Dec 2021 18:33:24 +0000 (18:33 +0000)
Because we time out channel info that is older than two weeks now,
we should also reject new channel info that is older than two
weeks, in addition to rejecting future channel info.

lightning/src/routing/network_graph.rs

index 67dc302246325b7efa219e98acdde875e5be702c..aa0e9f64fae69a0cf543d41c25ee0b4a9d3629d3 100644 (file)
@@ -1132,6 +1132,9 @@ impl NetworkGraph {
        /// You probably don't want to call this directly, instead relying on a NetGraphMsgHandler's
        /// RoutingMessageHandler implementation to call it indirectly. This may be useful to accept
        /// routing messages from a source using a protocol other than the lightning P2P protocol.
+       ///
+       /// If built with `no-std`, any updates with a timestamp more than two weeks in the past or
+       /// materially in the future will be rejected.
        pub fn update_channel<T: secp256k1::Verification>(&self, msg: &msgs::ChannelUpdate, secp_ctx: &Secp256k1<T>) -> Result<(), LightningError> {
                self.update_channel_intern(&msg.contents, Some(&msg), Some((&msg.signature, secp_ctx)))
        }
@@ -1139,6 +1142,9 @@ impl NetworkGraph {
        /// For an already known (from announcement) channel, update info about one of the directions
        /// of the channel without verifying the associated signatures. Because we aren't given the
        /// associated signatures here we cannot relay the channel update to any of our peers.
+       ///
+       /// If built with `no-std`, any updates with a timestamp more than two weeks in the past or
+       /// materially in the future will be rejected.
        pub fn update_channel_unsigned(&self, msg: &msgs::UnsignedChannelUpdate) -> Result<(), LightningError> {
                self.update_channel_intern(msg, None, None::<(&secp256k1::Signature, &Secp256k1<secp256k1::VerifyOnly>)>)
        }
@@ -1148,6 +1154,19 @@ impl NetworkGraph {
                let chan_enabled = msg.flags & (1 << 1) != (1 << 1);
                let chan_was_enabled;
 
+               #[cfg(all(feature = "std", not(test), not(feature = "_test_utils")))]
+               {
+                       // Note that many tests rely on being able to set arbitrarily old timestamps, thus we
+                       // disable this check during tests!
+                       let time = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time must be > 1970").as_secs();
+                       if (msg.timestamp as u64) < time - STALE_CHANNEL_UPDATE_AGE_LIMIT_SECS {
+                               return Err(LightningError{err: "channel_update is older than two weeks old".to_owned(), action: ErrorAction::IgnoreError});
+                       }
+                       if msg.timestamp as u64 > time + 60 * 60 * 24 {
+                               return Err(LightningError{err: "channel_update has a timestamp more than a day in the future".to_owned(), action: ErrorAction::IgnoreError});
+                       }
+               }
+
                let mut channels = self.channels.write().unwrap();
                match channels.get_mut(&msg.short_channel_id) {
                        None => return Err(LightningError{err: "Couldn't find channel for update".to_owned(), action: ErrorAction::IgnoreError}),