@@ -401,82 +401,91 @@ where C::Target: chain::Access, L::Target: Logger
401
401
return ( ) ;
402
402
}
403
403
404
- // Send a gossip_timestamp_filter to enable gossip message receipt. Note that we have to
405
- // use a "all timestamps" filter as sending the current timestamp would result in missing
406
- // gossip messages that are simply sent late. We could calculate the intended filter time
407
- // by looking at the current time and subtracting two weeks (before which we'll reject
408
- // messages), but there's not a lot of reason to bother - our peers should be discarding
409
- // the same messages.
404
+ // The lightning network's gossip sync system is completely broken in numerous ways.
405
+ //
406
+ // Given no broadly-available set-reconciliation protocol, the only reasonable approach is
407
+ // to do a full sync from the first few peers we connect to, and then receive gossip
408
+ // updates from all our peers normally.
409
+ //
410
+ // Originally, we could simply tell a peer to dump us the entire gossip table on startup,
411
+ // wasting lots of bandwidth but ensuring we have the full network graph. After the initial
412
+ // dump peers would always send gossip and we'd stay up-to-date with whatever our peer has
413
+ // seen.
414
+ //
415
+ // In order to reduce the bandwidth waste, "gossip queries" were introduced, allowing you
416
+ // to ask for the SCIDs of all channels in your peer's routing graph, and then only request
417
+ // channel data which you are missing. Except there was no way at all to identify which
418
+ // `channel_update`s you were missing, so you still had to request everything, just in a
419
+ // very complicated way with some queries instead of just getting the dump.
420
+ //
421
+ // Later, an option was added to fetch the latest timestamps of the `channel_update`s to
422
+ // make efficient sync possible, however it has yet to be implemented in lnd, which makes
423
+ // relying on it useless.
424
+ //
425
+ // After gossip queries were introduced, support for receiving a full gossip table dump on
426
+ // connection was removed from several nodes, making it impossible to get a full sync
427
+ // without using the "gossip queries" messages.
428
+ //
429
+ // Once you opt into "gossip queries" the only way to receive any gossip updates that a
430
+ // peer receives after you connect, you must send a `gossip_timestamp_filter` message. This
431
+ // message, as the name implies, tells the peer to not forward any gossip messages with a
432
+ // timestamp older than a given value (not the time the peer received the filter, but the
433
+ // timestamp in the update message, which is often hours behind when the peer received the
434
+ // message).
435
+ //
436
+ // Obnoxiously, `gossip_timestamp_filter` isn't *just* a filter, but its also a request for
437
+ // your peer to send you the full routing graph. Thus, in order to tell a peer to send you
438
+ // any updates as it sees them, you have to also ask for the full routing graph to be
439
+ // synced. If you set a timestamp filter near the current time, peers will simply not
440
+ // forward any new updates they see to you which were generated some time ago (which is
441
+ // not uncommon). If you instead set a timestamp filter near 0 (or two weeks ago), you will
442
+ // always get the full routing graph from all your peers.
443
+ //
444
+ // Most lightning nodes today opt to simply turn off receiving gossip data which only
445
+ // propagated some time after it was generated, and, worse, often disable gossiping with
446
+ // several peers after their first connection. The second behavior can cause gossip to not
447
+ // propagate fully if there are cuts in the gossiping subgraph.
448
+ //
449
+ // In an attempt to cut a middle ground between always fetching the full graph from all of
450
+ // our peers and never receiving gossip from peers at all, we send all of our peers a
451
+ // `gossip_timestamp_filter`, with the filter time set either two weeks ago or an hour ago.
452
+ //
453
+ // For no-std builds, we bury our head in the sand and do a full sync on each connection.
454
+ let should_request_full_sync = self . should_request_full_sync ( & their_node_id) ;
455
+ #[ allow( unused_mut, unused_assignments) ]
456
+ let mut gossip_start_time = 0 ;
457
+ #[ cfg( feature = "std" ) ]
458
+ {
459
+ gossip_start_time = SystemTime :: now ( ) . duration_since ( UNIX_EPOCH ) . expect ( "Time must be > 1970" ) . as_secs ( ) ;
460
+ if should_request_full_sync {
461
+ gossip_start_time -= 60 * 60 * 24 * 7 * 2 ; // 2 weeks ago
462
+ } else {
463
+ gossip_start_time -= 60 * 60 ; // an hour ago
464
+ }
465
+ }
466
+
410
467
let mut pending_events = self . pending_events . lock ( ) . unwrap ( ) ;
411
468
pending_events. push ( MessageSendEvent :: SendGossipTimestampFilter {
412
469
node_id : their_node_id. clone ( ) ,
413
470
msg : GossipTimestampFilter {
414
471
chain_hash : self . network_graph . genesis_hash ,
415
- first_timestamp : 0 ,
472
+ first_timestamp : gossip_start_time as u32 , // 2106 issue!
416
473
timestamp_range : u32:: max_value ( ) ,
417
474
} ,
418
475
} ) ;
419
-
420
- // Check if we need to perform a full synchronization with this peer
421
- if !self . should_request_full_sync ( & their_node_id) {
422
- return ( ) ;
423
- }
424
-
425
- let first_blocknum = 0 ;
426
- let number_of_blocks = 0xffffffff ;
427
- log_debug ! ( self . logger, "Sending query_channel_range peer={}, first_blocknum={}, number_of_blocks={}" , log_pubkey!( their_node_id) , first_blocknum, number_of_blocks) ;
428
- pending_events. push ( MessageSendEvent :: SendChannelRangeQuery {
429
- node_id : their_node_id. clone ( ) ,
430
- msg : QueryChannelRange {
431
- chain_hash : self . network_graph . genesis_hash ,
432
- first_blocknum,
433
- number_of_blocks,
434
- } ,
435
- } ) ;
436
476
}
437
477
438
- /// Statelessly processes a reply to a channel range query by immediately
439
- /// sending an SCID query with SCIDs in the reply. To keep this handler
440
- /// stateless, it does not validate the sequencing of replies for multi-
441
- /// reply ranges. It does not validate whether the reply(ies) cover the
442
- /// queried range. It also does not filter SCIDs to only those in the
443
- /// original query range. We also do not validate that the chain_hash
444
- /// matches the chain_hash of the NetworkGraph. Any chan_ann message that
445
- /// does not match our chain_hash will be rejected when the announcement is
446
- /// processed.
447
- fn handle_reply_channel_range ( & self , their_node_id : & PublicKey , msg : ReplyChannelRange ) -> Result < ( ) , LightningError > {
448
- log_debug ! ( self . logger, "Handling reply_channel_range peer={}, first_blocknum={}, number_of_blocks={}, sync_complete={}, scids={}" , log_pubkey!( their_node_id) , msg. first_blocknum, msg. number_of_blocks, msg. sync_complete, msg. short_channel_ids. len( ) , ) ;
449
-
450
- log_debug ! ( self . logger, "Sending query_short_channel_ids peer={}, batch_size={}" , log_pubkey!( their_node_id) , msg. short_channel_ids. len( ) ) ;
451
- let mut pending_events = self . pending_events . lock ( ) . unwrap ( ) ;
452
- pending_events. push ( MessageSendEvent :: SendShortIdsQuery {
453
- node_id : their_node_id. clone ( ) ,
454
- msg : QueryShortChannelIds {
455
- chain_hash : msg. chain_hash ,
456
- short_channel_ids : msg. short_channel_ids ,
457
- }
458
- } ) ;
459
-
478
+ fn handle_reply_channel_range ( & self , _their_node_id : & PublicKey , _msg : ReplyChannelRange ) -> Result < ( ) , LightningError > {
479
+ // We don't make queries, so should never receive replies. If, in the future, the set
480
+ // reconciliation extensions to gossip queries become broadly supported, we should revert
481
+ // this code to its state pre-0.0.106.
460
482
Ok ( ( ) )
461
483
}
462
484
463
- /// When an SCID query is initiated the remote peer will begin streaming
464
- /// gossip messages. In the event of a failure, we may have received
465
- /// some channel information. Before trying with another peer, the
466
- /// caller should update its set of SCIDs that need to be queried.
467
- fn handle_reply_short_channel_ids_end ( & self , their_node_id : & PublicKey , msg : ReplyShortChannelIdsEnd ) -> Result < ( ) , LightningError > {
468
- log_debug ! ( self . logger, "Handling reply_short_channel_ids_end peer={}, full_information={}" , log_pubkey!( their_node_id) , msg. full_information) ;
469
-
470
- // If the remote node does not have up-to-date information for the
471
- // chain_hash they will set full_information=false. We can fail
472
- // the result and try again with a different peer.
473
- if !msg. full_information {
474
- return Err ( LightningError {
475
- err : String :: from ( "Received reply_short_channel_ids_end with no information" ) ,
476
- action : ErrorAction :: IgnoreError
477
- } ) ;
478
- }
479
-
485
+ fn handle_reply_short_channel_ids_end ( & self , _their_node_id : & PublicKey , _msg : ReplyShortChannelIdsEnd ) -> Result < ( ) , LightningError > {
486
+ // We don't make queries, so should never receive replies. If, in the future, the set
487
+ // reconciliation extensions to gossip queries become broadly supported, we should revert
488
+ // this code to its state pre-0.0.106.
480
489
Ok ( ( ) )
481
490
}
482
491
@@ -1535,7 +1544,7 @@ mod tests {
1535
1544
use routing:: network_graph:: { NetGraphMsgHandler , NetworkGraph , NetworkUpdate , MAX_EXCESS_BYTES_FOR_RELAY } ;
1536
1545
use ln:: msgs:: { Init , OptionalField , RoutingMessageHandler , UnsignedNodeAnnouncement , NodeAnnouncement ,
1537
1546
UnsignedChannelAnnouncement , ChannelAnnouncement , UnsignedChannelUpdate , ChannelUpdate ,
1538
- ReplyChannelRange , ReplyShortChannelIdsEnd , QueryChannelRange , QueryShortChannelIds , MAX_VALUE_MSAT } ;
1547
+ ReplyChannelRange , QueryChannelRange , QueryShortChannelIds , MAX_VALUE_MSAT } ;
1539
1548
use util:: test_utils;
1540
1549
use util:: logger:: Logger ;
1541
1550
use util:: ser:: { Readable , Writeable } ;
@@ -2272,15 +2281,16 @@ mod tests {
2272
2281
}
2273
2282
2274
2283
#[ test]
2284
+ #[ cfg( feature = "std" ) ]
2275
2285
fn calling_sync_routing_table ( ) {
2286
+ use std:: time:: { SystemTime , UNIX_EPOCH } ;
2287
+
2276
2288
let network_graph = create_network_graph ( ) ;
2277
2289
let ( secp_ctx, net_graph_msg_handler) = create_net_graph_msg_handler ( & network_graph) ;
2278
2290
let node_privkey_1 = & SecretKey :: from_slice ( & [ 42 ; 32 ] ) . unwrap ( ) ;
2279
2291
let node_id_1 = PublicKey :: from_secret_key ( & secp_ctx, node_privkey_1) ;
2280
2292
2281
2293
let chain_hash = genesis_block ( Network :: Testnet ) . header . block_hash ( ) ;
2282
- let first_blocknum = 0 ;
2283
- let number_of_blocks = 0xffff_ffff ;
2284
2294
2285
2295
// It should ignore if gossip_queries feature is not enabled
2286
2296
{
@@ -2290,132 +2300,23 @@ mod tests {
2290
2300
assert_eq ! ( events. len( ) , 0 ) ;
2291
2301
}
2292
2302
2293
- // It should send a query_channel_message with the correct information
2303
+ // It should send a gossip_timestamp_filter with the correct information
2294
2304
{
2295
2305
let init_msg = Init { features : InitFeatures :: known ( ) , remote_network_address : None } ;
2296
2306
net_graph_msg_handler. peer_connected ( & node_id_1, & init_msg) ;
2297
2307
let events = net_graph_msg_handler. get_and_clear_pending_msg_events ( ) ;
2298
- assert_eq ! ( events. len( ) , 2 ) ;
2308
+ assert_eq ! ( events. len( ) , 1 ) ;
2299
2309
match & events[ 0 ] {
2300
2310
MessageSendEvent :: SendGossipTimestampFilter { node_id, msg } => {
2301
2311
assert_eq ! ( node_id, & node_id_1) ;
2302
2312
assert_eq ! ( msg. chain_hash, chain_hash) ;
2303
- assert_eq ! ( msg. first_timestamp, 0 ) ;
2313
+ let expected_timestamp = SystemTime :: now ( ) . duration_since ( UNIX_EPOCH ) . expect ( "Time must be > 1970" ) . as_secs ( ) ;
2314
+ assert ! ( ( msg. first_timestamp as u64 ) >= expected_timestamp - 60 * 60 * 24 * 7 * 2 ) ;
2315
+ assert ! ( ( msg. first_timestamp as u64 ) < expected_timestamp - 60 * 60 * 24 * 7 * 2 + 10 ) ;
2304
2316
assert_eq ! ( msg. timestamp_range, u32 :: max_value( ) ) ;
2305
2317
} ,
2306
2318
_ => panic ! ( "Expected MessageSendEvent::SendChannelRangeQuery" )
2307
2319
} ;
2308
- match & events[ 1 ] {
2309
- MessageSendEvent :: SendChannelRangeQuery { node_id, msg } => {
2310
- assert_eq ! ( node_id, & node_id_1) ;
2311
- assert_eq ! ( msg. chain_hash, chain_hash) ;
2312
- assert_eq ! ( msg. first_blocknum, first_blocknum) ;
2313
- assert_eq ! ( msg. number_of_blocks, number_of_blocks) ;
2314
- } ,
2315
- _ => panic ! ( "Expected MessageSendEvent::SendChannelRangeQuery" )
2316
- } ;
2317
- }
2318
-
2319
- // It should not enqueue a query when should_request_full_sync return false.
2320
- // The initial implementation allows syncing with the first 5 peers after
2321
- // which should_request_full_sync will return false
2322
- {
2323
- let network_graph = create_network_graph ( ) ;
2324
- let ( secp_ctx, net_graph_msg_handler) = create_net_graph_msg_handler ( & network_graph) ;
2325
- let init_msg = Init { features : InitFeatures :: known ( ) , remote_network_address : None } ;
2326
- for n in 1 ..7 {
2327
- let node_privkey = & SecretKey :: from_slice ( & [ n; 32 ] ) . unwrap ( ) ;
2328
- let node_id = PublicKey :: from_secret_key ( & secp_ctx, node_privkey) ;
2329
- net_graph_msg_handler. peer_connected ( & node_id, & init_msg) ;
2330
- let events = net_graph_msg_handler. get_and_clear_pending_msg_events ( ) ;
2331
- if n <= 5 {
2332
- assert_eq ! ( events. len( ) , 2 ) ;
2333
- } else {
2334
- // Even after the we stop sending the explicit query, we should still send a
2335
- // gossip_timestamp_filter on each new connection.
2336
- assert_eq ! ( events. len( ) , 1 ) ;
2337
- }
2338
-
2339
- }
2340
- }
2341
- }
2342
-
2343
- #[ test]
2344
- fn handling_reply_channel_range ( ) {
2345
- let network_graph = create_network_graph ( ) ;
2346
- let ( secp_ctx, net_graph_msg_handler) = create_net_graph_msg_handler ( & network_graph) ;
2347
- let node_privkey_1 = & SecretKey :: from_slice ( & [ 42 ; 32 ] ) . unwrap ( ) ;
2348
- let node_id_1 = PublicKey :: from_secret_key ( & secp_ctx, node_privkey_1) ;
2349
-
2350
- let chain_hash = genesis_block ( Network :: Testnet ) . header . block_hash ( ) ;
2351
-
2352
- // Test receipt of a single reply that should enqueue an SCID query
2353
- // matching the SCIDs in the reply
2354
- {
2355
- let result = net_graph_msg_handler. handle_reply_channel_range ( & node_id_1, ReplyChannelRange {
2356
- chain_hash,
2357
- sync_complete : true ,
2358
- first_blocknum : 0 ,
2359
- number_of_blocks : 2000 ,
2360
- short_channel_ids : vec ! [
2361
- 0x0003e0_000000_0000 , // 992x0x0
2362
- 0x0003e8_000000_0000 , // 1000x0x0
2363
- 0x0003e9_000000_0000 , // 1001x0x0
2364
- 0x0003f0_000000_0000 , // 1008x0x0
2365
- 0x00044c_000000_0000 , // 1100x0x0
2366
- 0x0006e0_000000_0000 , // 1760x0x0
2367
- ] ,
2368
- } ) ;
2369
- assert ! ( result. is_ok( ) ) ;
2370
-
2371
- // We expect to emit a query_short_channel_ids message with the received scids
2372
- let events = net_graph_msg_handler. get_and_clear_pending_msg_events ( ) ;
2373
- assert_eq ! ( events. len( ) , 1 ) ;
2374
- match & events[ 0 ] {
2375
- MessageSendEvent :: SendShortIdsQuery { node_id, msg } => {
2376
- assert_eq ! ( node_id, & node_id_1) ;
2377
- assert_eq ! ( msg. chain_hash, chain_hash) ;
2378
- assert_eq ! ( msg. short_channel_ids, vec![
2379
- 0x0003e0_000000_0000 , // 992x0x0
2380
- 0x0003e8_000000_0000 , // 1000x0x0
2381
- 0x0003e9_000000_0000 , // 1001x0x0
2382
- 0x0003f0_000000_0000 , // 1008x0x0
2383
- 0x00044c_000000_0000 , // 1100x0x0
2384
- 0x0006e0_000000_0000 , // 1760x0x0
2385
- ] ) ;
2386
- } ,
2387
- _ => panic ! ( "expected MessageSendEvent::SendShortIdsQuery" ) ,
2388
- }
2389
- }
2390
- }
2391
-
2392
- #[ test]
2393
- fn handling_reply_short_channel_ids ( ) {
2394
- let network_graph = create_network_graph ( ) ;
2395
- let ( secp_ctx, net_graph_msg_handler) = create_net_graph_msg_handler ( & network_graph) ;
2396
- let node_privkey = & SecretKey :: from_slice ( & [ 41 ; 32 ] ) . unwrap ( ) ;
2397
- let node_id = PublicKey :: from_secret_key ( & secp_ctx, node_privkey) ;
2398
-
2399
- let chain_hash = genesis_block ( Network :: Testnet ) . header . block_hash ( ) ;
2400
-
2401
- // Test receipt of a successful reply
2402
- {
2403
- let result = net_graph_msg_handler. handle_reply_short_channel_ids_end ( & node_id, ReplyShortChannelIdsEnd {
2404
- chain_hash,
2405
- full_information : true ,
2406
- } ) ;
2407
- assert ! ( result. is_ok( ) ) ;
2408
- }
2409
-
2410
- // Test receipt of a reply that indicates the peer does not maintain up-to-date information
2411
- // for the chain_hash requested in the query.
2412
- {
2413
- let result = net_graph_msg_handler. handle_reply_short_channel_ids_end ( & node_id, ReplyShortChannelIdsEnd {
2414
- chain_hash,
2415
- full_information : false ,
2416
- } ) ;
2417
- assert ! ( result. is_err( ) ) ;
2418
- assert_eq ! ( result. err( ) . unwrap( ) . err, "Received reply_short_channel_ids_end with no information" ) ;
2419
2320
}
2420
2321
}
2421
2322
0 commit comments