Skip to content

Commit e742894

Browse files
committed
Change routing table sync to use gossip_queries
This commit changes outbound routing table sync to use gossip_queries instead of the effectively deprecated initial_routing_sync feature. This change removes setting of initial_routing_sync in our outbound Init message. Instead we now call sync_routing_table after receiving an Init message from a peer. If the peer supports gossip_queries and should_request_full_sync returns true, we initiate a full gossip_queries sync.
1 parent 7a4a29f commit e742894

File tree

4 files changed

+55
-67
lines changed

4 files changed

+55
-67
lines changed

lightning/src/ln/features.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,7 @@ impl<T: sealed::GossipQueries> Features<T> {
484484
pub(crate) fn supports_gossip_queries(&self) -> bool {
485485
<T as sealed::GossipQueries>::supports_feature(&self.flags)
486486
}
487+
#[cfg(test)]
487488
pub(crate) fn clear_gossip_queries(mut self) -> Self {
488489
<T as sealed::GossipQueries>::clear_bits(&mut self.flags);
489490
self
@@ -514,6 +515,10 @@ impl<T: sealed::InitialRoutingSync> Features<T> {
514515
pub(crate) fn initial_routing_sync(&self) -> bool {
515516
<T as sealed::InitialRoutingSync>::supports_feature(&self.flags)
516517
}
518+
// We are no longer setting initial_routing_sync now that gossip_queries
519+
// is enabled. This feature is ignored by a peer when gossip_queries has
520+
// been negotiated.
521+
#[cfg(test)]
517522
pub(crate) fn clear_initial_routing_sync(&mut self) {
518523
<T as sealed::InitialRoutingSync>::clear_bits(&mut self.flags)
519524
}

lightning/src/ln/msgs.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,12 @@ pub trait ChannelMessageHandler : events::MessageSendEventsProvider + Send + Syn
804804
}
805805

806806
/// A trait to describe an object which can receive routing messages.
807+
///
808+
/// # Implementor DoS Warnings
809+
///
810+
/// For `gossip_queries` messages there are potential DoS vectors when handling
811+
/// inbound queries. Implementors using an on-disk network graph should be aware of
812+
/// repeated disk I/O for queries accessing different parts of the network graph.
807813
pub trait RoutingMessageHandler : Send + Sync + events::MessageSendEventsProvider {
808814
/// Handle an incoming node_announcement message, returning true if it should be forwarded on,
809815
/// false or returning an Err otherwise.
@@ -841,14 +847,10 @@ pub trait RoutingMessageHandler : Send + Sync + events::MessageSendEventsProvide
841847
/// gossip messages.
842848
fn handle_reply_short_channel_ids_end(&self, their_node_id: &PublicKey, msg: ReplyShortChannelIdsEnd) -> Result<(), LightningError>;
843849
/// Handles when a peer asks us to send a list of short_channel_ids
844-
/// for the requested range of blocks. There are potential DoS vectors when
845-
/// handling inbound queries. Handling requests with first_blocknum very far
846-
/// away may trigger repeated disk I/O if the NetworkGraph is not fully in-memory.
850+
/// for the requested range of blocks.
847851
fn handle_query_channel_range(&self, their_node_id: &PublicKey, msg: QueryChannelRange) -> Result<(), LightningError>;
848852
/// Handles when a peer asks us to send routing gossip messages for a
849-
/// list of short_channel_ids. There are potential DoS vectors when handling
850-
/// inbound queries. Handling requests with first_blocknum very far away may
851-
/// trigger repeated disk I/O if the NetworkGraph is not fully in-memory.
853+
/// list of short_channel_ids.
852854
fn handle_query_short_channel_ids(&self, their_node_id: &PublicKey, msg: QueryShortChannelIds) -> Result<(), LightningError>;
853855
}
854856

lightning/src/ln/peer_handler.rs

Lines changed: 4 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -584,11 +584,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, L: Deref> PeerManager<D
584584

585585
peer.their_node_id = Some(their_node_id);
586586
insert_node_id!();
587-
let mut features = InitFeatures::known().clear_gossip_queries();
588-
if !self.message_handler.route_handler.should_request_full_sync(&peer.their_node_id.unwrap()) {
589-
features.clear_initial_routing_sync();
590-
}
591-
587+
let features = InitFeatures::known();
592588
let resp = msgs::Init { features };
593589
self.enqueue_message(&mut peers.peers_needing_send, peer, peer_descriptor.clone(), &resp);
594590
},
@@ -713,15 +709,13 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, L: Deref> PeerManager<D
713709
}
714710

715711
if !peer.outbound {
716-
let mut features = InitFeatures::known().clear_gossip_queries();
717-
if !self.message_handler.route_handler.should_request_full_sync(&peer.their_node_id.unwrap()) {
718-
features.clear_initial_routing_sync();
719-
}
720-
712+
let features = InitFeatures::known();
721713
let resp = msgs::Init { features };
722714
self.enqueue_message(peers_needing_send, peer, peer_descriptor.clone(), &resp);
723715
}
724716

717+
self.message_handler.route_handler.sync_routing_table(&peer.their_node_id.unwrap(), &msg);
718+
725719
self.message_handler.chan_handler.peer_connected(&peer.their_node_id.unwrap(), &msg);
726720
peer.their_features = Some(msg.features);
727721
},
@@ -1329,13 +1323,6 @@ mod tests {
13291323
(fd_a.clone(), fd_b.clone())
13301324
}
13311325

1332-
fn establish_connection_and_read_events<'a>(peer_a: &PeerManager<FileDescriptor, &'a test_utils::TestChannelMessageHandler, &'a test_utils::TestRoutingMessageHandler, &'a test_utils::TestLogger>, peer_b: &PeerManager<FileDescriptor, &'a test_utils::TestChannelMessageHandler, &'a test_utils::TestRoutingMessageHandler, &'a test_utils::TestLogger>) -> (FileDescriptor, FileDescriptor) {
1333-
let (mut fd_a, mut fd_b) = establish_connection(peer_a, peer_b);
1334-
assert_eq!(peer_b.read_event(&mut fd_b, &fd_a.outbound_data.lock().unwrap().split_off(0)).unwrap(), false);
1335-
assert_eq!(peer_a.read_event(&mut fd_a, &fd_b.outbound_data.lock().unwrap().split_off(0)).unwrap(), false);
1336-
(fd_a.clone(), fd_b.clone())
1337-
}
1338-
13391326
#[test]
13401327
fn test_disconnect_peer() {
13411328
// Simple test which builds a network of PeerManager, connects and brings them to NoiseState::Finished and
@@ -1404,41 +1391,4 @@ mod tests {
14041391
assert_eq!(cfgs[1].routing_handler.chan_upds_recvd.load(Ordering::Acquire), 100);
14051392
assert_eq!(cfgs[1].routing_handler.chan_anns_recvd.load(Ordering::Acquire), 50);
14061393
}
1407-
1408-
#[test]
1409-
fn limit_initial_routing_sync_requests() {
1410-
// Inbound peer 0 requests initial_routing_sync, but outbound peer 1 does not.
1411-
{
1412-
let cfgs = create_peermgr_cfgs(2);
1413-
cfgs[0].routing_handler.request_full_sync.store(true, Ordering::Release);
1414-
let peers = create_network(2, &cfgs);
1415-
let (fd_0_to_1, fd_1_to_0) = establish_connection_and_read_events(&peers[0], &peers[1]);
1416-
1417-
let peer_0 = peers[0].peers.lock().unwrap();
1418-
let peer_1 = peers[1].peers.lock().unwrap();
1419-
1420-
let peer_0_features = peer_1.peers.get(&fd_1_to_0).unwrap().their_features.as_ref();
1421-
let peer_1_features = peer_0.peers.get(&fd_0_to_1).unwrap().their_features.as_ref();
1422-
1423-
assert!(peer_0_features.unwrap().initial_routing_sync());
1424-
assert!(!peer_1_features.unwrap().initial_routing_sync());
1425-
}
1426-
1427-
// Outbound peer 1 requests initial_routing_sync, but inbound peer 0 does not.
1428-
{
1429-
let cfgs = create_peermgr_cfgs(2);
1430-
cfgs[1].routing_handler.request_full_sync.store(true, Ordering::Release);
1431-
let peers = create_network(2, &cfgs);
1432-
let (fd_0_to_1, fd_1_to_0) = establish_connection_and_read_events(&peers[0], &peers[1]);
1433-
1434-
let peer_0 = peers[0].peers.lock().unwrap();
1435-
let peer_1 = peers[1].peers.lock().unwrap();
1436-
1437-
let peer_0_features = peer_1.peers.get(&fd_1_to_0).unwrap().their_features.as_ref();
1438-
let peer_1_features = peer_0.peers.get(&fd_0_to_1).unwrap().their_features.as_ref();
1439-
1440-
assert!(!peer_0_features.unwrap().initial_routing_sync());
1441-
assert!(peer_1_features.unwrap().initial_routing_sync());
1442-
}
1443-
}
14441394
}

lightning/src/routing/network_graph.rs

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -219,17 +219,26 @@ impl<C: Deref + Sync + Send, L: Deref + Sync + Send> RoutingMessageHandler for N
219219
}
220220

221221
/// Initiates a stateless sync of routing gossip information with a peer
222-
/// by calling query_channel_range. The default strategy used by this
223-
/// implementation is to sync for the full block range with several peers.
222+
/// using gossip_queries. The default strategy used by this implementation
223+
/// is to sync the full block range with several peers.
224+
///
224225
/// We should expect one or more reply_channel_range messages in response
225-
/// to our query. Each reply will enqueue a query_scid message to request
226-
/// gossip messages for each channel. The sync is considered complete when
227-
/// the final reply_scids_end message is received, though we are not
226+
/// to our query_channel_range. Each reply will enqueue a query_scid message
227+
/// to request gossip messages for each channel. The sync is considered complete
228+
/// when the final reply_scids_end message is received, though we are not
228229
/// tracking this directly.
229230
fn sync_routing_table(&self, their_node_id: &PublicKey, init_msg: &Init) {
231+
232+
// We will only perform a sync with peers that support gossip_queries.
230233
if !init_msg.features.supports_gossip_queries() {
231234
return ();
232235
}
236+
237+
// Check if we need to perform a full synchronization with this peer
238+
if !self.should_request_full_sync(their_node_id) {
239+
return ();
240+
}
241+
233242
let first_blocknum = 0;
234243
let number_of_blocks = 0xffffffff;
235244
log_debug!(self.logger, "Sending query_channel_range peer={}, first_blocknum={}, number_of_blocks={}", log_pubkey!(their_node_id), first_blocknum, number_of_blocks);
@@ -249,7 +258,10 @@ impl<C: Deref + Sync + Send, L: Deref + Sync + Send> RoutingMessageHandler for N
249258
/// stateless, it does not validate the sequencing of replies for multi-
250259
/// reply ranges. It does not validate whether the reply(ies) cover the
251260
/// queried range. It also does not filter SCIDs to only those in the
252-
/// original query range.
261+
/// original query range. We also do not validate that the chain_hash
262+
/// matches the chain_hash of the NetworkGraph. Any chan_ann message that
263+
/// does not match our chain_hash will be rejected when the announcement is
264+
/// processed.
253265
fn handle_reply_channel_range(&self, their_node_id: &PublicKey, msg: ReplyChannelRange) -> Result<(), LightningError> {
254266
log_debug!(self.logger, "Handling reply_channel_range peer={}, first_blocknum={}, number_of_blocks={}, full_information={}, scids={}", log_pubkey!(their_node_id), msg.first_blocknum, msg.number_of_blocks, msg.full_information, msg.short_channel_ids.len(),);
255267

@@ -1967,6 +1979,26 @@ mod tests {
19671979
_ => panic!("Expected MessageSendEvent::SendChannelRangeQuery")
19681980
};
19691981
}
1982+
1983+
// It should not enqueue a query when should_request_full_sync return false.
1984+
// The initial implementation allows syncing with the first 5 peers after
1985+
// which should_request_full_sync will return false
1986+
{
1987+
let (secp_ctx, net_graph_msg_handler) = create_net_graph_msg_handler();
1988+
let init_msg = Init { features: InitFeatures::known() };
1989+
for n in 1..7 {
1990+
let node_privkey = &SecretKey::from_slice(&[n; 32]).unwrap();
1991+
let node_id = PublicKey::from_secret_key(&secp_ctx, node_privkey);
1992+
net_graph_msg_handler.sync_routing_table(&node_id, &init_msg);
1993+
let events = net_graph_msg_handler.get_and_clear_pending_msg_events();
1994+
if n <= 5 {
1995+
assert_eq!(events.len(), 1);
1996+
} else {
1997+
assert_eq!(events.len(), 0);
1998+
}
1999+
2000+
}
2001+
}
19702002
}
19712003

19722004
#[test]
@@ -1980,7 +2012,6 @@ mod tests {
19802012
// Test receipt of a single reply that should enqueue an SCID query
19812013
// matching the SCIDs in the reply
19822014
{
1983-
// Handle a single successful reply that encompasses the queried channel range
19842015
let result = net_graph_msg_handler.handle_reply_channel_range(&node_id_1, ReplyChannelRange {
19852016
chain_hash,
19862017
full_information: true,

0 commit comments

Comments
 (0)