Send a `gossip_timestamp_filter` on connect to enable gossip sync 2022-03-fix-post-start-sync
authorMatt Corallo <git@bluematt.me>
Thu, 17 Mar 2022 22:14:43 +0000 (22:14 +0000)
committerMatt Corallo <git@bluematt.me>
Thu, 17 Mar 2022 22:18:33 +0000 (22:18 +0000)
On connection, if our peer supports gossip queries, and we never
send a `gossip_timestamp_filter`, our peer is supposed to never
send us gossip outside of explicit queries. Thus, we'll end up
always having stale gossip information after the first few
connections we make to peers.

The solution is to send a dummy `gossip_timestamp_filter`
immediately after connecting to peers.

lightning/src/ln/channelmanager.rs
lightning/src/ln/peer_handler.rs
lightning/src/routing/network_graph.rs
lightning/src/util/events.rs

index f3913c5167c8ebc70d0b1cfadb20568908555133..3214bd4deb9403e35a5b3d898c7db4b452ad788f 100644 (file)
@@ -5893,6 +5893,7 @@ impl<Signer: Sign, M: Deref , T: Deref , K: Deref , F: Deref , L: Deref >
                                        &events::MessageSendEvent::SendChannelRangeQuery { .. } => false,
                                        &events::MessageSendEvent::SendShortIdsQuery { .. } => false,
                                        &events::MessageSendEvent::SendReplyChannelRange { .. } => false,
+                                       &events::MessageSendEvent::SendGossipTimestampFilter { .. } => false,
                                }
                        });
                }
index 9d79c6385f45173a794e3ea46fb8c5c054db6d3f..4c4e22c0c2b6b57020e789088e184721f9fd8e26 100644 (file)
@@ -1477,6 +1477,9 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, L: Deref, CMH: Deref> P
                                                        msg.sync_complete);
                                                self.enqueue_message(get_peer_for_forwarding!(node_id), msg);
                                        }
+                                       MessageSendEvent::SendGossipTimestampFilter { ref node_id, ref msg } => {
+                                               self.enqueue_message(get_peer_for_forwarding!(node_id), msg);
+                                       }
                                }
                        }
 
index 8f3511d6dd6691f2755de5370964aea3e15ffe8b..e7c8271bf35226cc96f02365d39c9f5d54c07638 100644 (file)
@@ -25,7 +25,7 @@ use chain;
 use chain::Access;
 use ln::features::{ChannelFeatures, NodeFeatures};
 use ln::msgs::{DecodeError, ErrorAction, Init, LightningError, RoutingMessageHandler, NetAddress, MAX_VALUE_MSAT};
-use ln::msgs::{ChannelAnnouncement, ChannelUpdate, NodeAnnouncement, OptionalField};
+use ln::msgs::{ChannelAnnouncement, ChannelUpdate, NodeAnnouncement, OptionalField, GossipTimestampFilter};
 use ln::msgs::{QueryChannelRange, ReplyChannelRange, QueryShortChannelIds, ReplyShortChannelIdsEnd};
 use ln::msgs;
 use util::ser::{Writeable, Readable, Writer};
@@ -401,6 +401,22 @@ where C::Target: chain::Access, L::Target: Logger
                        return ();
                }
 
+               // Send a gossip_timestamp_filter to enable gossip message receipt. Note that we have to
+               // use a "all timestamps" filter as sending the current timestamp would result in missing
+               // gossip messages that are simply sent late. We could calculate the intended filter time
+               // by looking at the current time and subtracting two weeks (before which we'll reject
+               // messages), but there's not a lot of reason to bother - our peers should be discarding
+               // the same messages.
+               let mut pending_events = self.pending_events.lock().unwrap();
+               pending_events.push(MessageSendEvent::SendGossipTimestampFilter {
+                       node_id: their_node_id.clone(),
+                       msg: GossipTimestampFilter {
+                               chain_hash: self.network_graph.genesis_hash,
+                               first_timestamp: 0,
+                               timestamp_range: u32::max_value(),
+                       },
+               });
+
                // Check if we need to perform a full synchronization with this peer
                if !self.should_request_full_sync(&their_node_id) {
                        return ();
@@ -409,7 +425,6 @@ where C::Target: chain::Access, L::Target: Logger
                let first_blocknum = 0;
                let number_of_blocks = 0xffffffff;
                log_debug!(self.logger, "Sending query_channel_range peer={}, first_blocknum={}, number_of_blocks={}", log_pubkey!(their_node_id), first_blocknum, number_of_blocks);
-               let mut pending_events = self.pending_events.lock().unwrap();
                pending_events.push(MessageSendEvent::SendChannelRangeQuery {
                        node_id: their_node_id.clone(),
                        msg: QueryChannelRange {
@@ -2280,8 +2295,17 @@ mod tests {
                        let init_msg = Init { features: InitFeatures::known() };
                        net_graph_msg_handler.peer_connected(&node_id_1, &init_msg);
                        let events = net_graph_msg_handler.get_and_clear_pending_msg_events();
-                       assert_eq!(events.len(), 1);
+                       assert_eq!(events.len(), 2);
                        match &events[0] {
+                               MessageSendEvent::SendGossipTimestampFilter{ node_id, msg } => {
+                                       assert_eq!(node_id, &node_id_1);
+                                       assert_eq!(msg.chain_hash, chain_hash);
+                                       assert_eq!(msg.first_timestamp, 0);
+                                       assert_eq!(msg.timestamp_range, u32::max_value());
+                               },
+                               _ => panic!("Expected MessageSendEvent::SendChannelRangeQuery")
+                       };
+                       match &events[1] {
                                MessageSendEvent::SendChannelRangeQuery{ node_id, msg } => {
                                        assert_eq!(node_id, &node_id_1);
                                        assert_eq!(msg.chain_hash, chain_hash);
@@ -2305,9 +2329,11 @@ mod tests {
                                net_graph_msg_handler.peer_connected(&node_id, &init_msg);
                                let events = net_graph_msg_handler.get_and_clear_pending_msg_events();
                                if n <= 5 {
-                                       assert_eq!(events.len(), 1);
+                                       assert_eq!(events.len(), 2);
                                } else {
-                                       assert_eq!(events.len(), 0);
+                                       // Even after the we stop sending the explicit query, we should still send a
+                                       // gossip_timestamp_filter on each new connection.
+                                       assert_eq!(events.len(), 1);
                                }
 
                        }
index 3b90015cab901bd0ba72586ffad37dd65d3be711..623b2ea01acb9cf623bc2a4f7bd73e8f32a404ce 100644 (file)
@@ -909,7 +909,15 @@ pub enum MessageSendEvent {
                node_id: PublicKey,
                /// The reply_channel_range which should be sent.
                msg: msgs::ReplyChannelRange,
-       }
+       },
+       /// Sends a timestamp filter for inbound gossip. This should be sent on each new connection to
+       /// enable receiving gossip messages from the peer.
+       SendGossipTimestampFilter {
+               /// The node_id of this message recipient
+               node_id: PublicKey,
+               /// The gossip_timestamp_filter which should be sent.
+               msg: msgs::GossipTimestampFilter,
+       },
 }
 
 /// A trait indicating an object may generate message send events