From 3cca221f8b41e9a42df748f972d14d851c826626 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 17 Mar 2022 22:14:43 +0000 Subject: [PATCH] Send a `gossip_timestamp_filter` on connect to enable gossip sync 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 | 1 + lightning/src/ln/peer_handler.rs | 3 +++ lightning/src/routing/network_graph.rs | 36 ++++++++++++++++++++++---- lightning/src/util/events.rs | 10 ++++++- 4 files changed, 44 insertions(+), 6 deletions(-) diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index f3913c516..3214bd4de 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -5893,6 +5893,7 @@ impl &events::MessageSendEvent::SendChannelRangeQuery { .. } => false, &events::MessageSendEvent::SendShortIdsQuery { .. } => false, &events::MessageSendEvent::SendReplyChannelRange { .. } => false, + &events::MessageSendEvent::SendGossipTimestampFilter { .. } => false, } }); } diff --git a/lightning/src/ln/peer_handler.rs b/lightning/src/ln/peer_handler.rs index 9d79c6385..4c4e22c0c 100644 --- a/lightning/src/ln/peer_handler.rs +++ b/lightning/src/ln/peer_handler.rs @@ -1477,6 +1477,9 @@ impl 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); + } } } diff --git a/lightning/src/routing/network_graph.rs b/lightning/src/routing/network_graph.rs index 8f3511d6d..e7c8271bf 100644 --- a/lightning/src/routing/network_graph.rs +++ b/lightning/src/routing/network_graph.rs @@ -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); } } diff --git a/lightning/src/util/events.rs b/lightning/src/util/events.rs index 3b90015ca..623b2ea01 100644 --- a/lightning/src/util/events.rs +++ b/lightning/src/util/events.rs @@ -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 -- 2.39.5