-
Notifications
You must be signed in to change notification settings - Fork 404
Support only one GossipSync
in BackgroundProcessor
#1517
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support only one GossipSync
in BackgroundProcessor
#1517
Conversation
P2PGossipSync has a Secp256k1 context field, which it only uses to pass to NetworkGraph methods. Move the field to NetworkGraph so other callers don't need to pass in a Secp256k1 context.
Codecov Report
@@ Coverage Diff @@
## main #1517 +/- ##
==========================================
- Coverage 90.95% 90.93% -0.03%
==========================================
Files 80 80
Lines 43347 43426 +79
Branches 43347 43426 +79
==========================================
+ Hits 39428 39488 +60
- Misses 3919 3938 +19
Continue to review full report at Codecov.
|
lightning/src/routing/gossip.rs
Outdated
log_debug!(self.logger, "{} node graph entry for {} due to a payment failure.", action, node_id); | ||
self.network_graph.node_failed(node_id, is_permanent); | ||
}, | ||
impl<G: Deref<Target = NetworkGraph>, L: Deref> EventHandler for (&G, &L) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is pretty awkward, and I don't see why its worth the effort just to avoid storing a Deref<Logger>
in the NetworkGraph
itself - IMO there's not really any reason we shouldn't have a logger reference in basically any struct, and definitely so if it causes awkward stuff here instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Figured this was the simplest approach, but doesn't look like there's many places where we instantiate a NetworkGraph
. So I can update it to take a Logger
, if you prefer.
Any reason why we implement Clone
for NetworkGraph
? That means we'd need the parameterization to be L::Target: Logger + Clone
, I think. Removing the Clone
implementation doesn't break any tests, AFAICT.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, found 6c569d8. 🙁
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe the reasoning isn't relevant anymore given P2PGossipSync
doesn't own the NetworkGraph
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm, it's probably still relevant, but we can deal with it downstream (maybe make Logger require clone for bindings?). Let's Do It Right in Rust and we can deal with bindings things in bindings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright, this is turning out to be more involved than I thought. Need a second pair of eyes on how to resolve this:
Checking lightning-invoice v0.14.0 (/Users/jkczyz/src/rust-lightning/lightning-invoice)
error[E0308]: mismatched types
--> lightning-invoice/src/utils.rs:469:63
|
458 | impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, S: Score> Router<S> for DefaultRouter<G, L>
| - this type parameter
...
469 | find_route(payer, params, &*self.network_graph, first_hops, &*self.logger, scorer, &random_seed_bytes)
| ^^^^^^^^^^^^^ expected type parameter `L`, found reference
|
= note: expected type parameter `L`
found reference `&<L as Deref>::Target`
From what I can tell, we're trying to pass find_route
two different types for L
but it wants them to be the same. Is the solution to just make two type parameters? (i.e., one for the network graph and one for the logger)
Here's the WIP commit with the compilation error: jkczyz@0f5bcd1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or maybe update find_route
to take &ReadOnlyNetworkGraph
like get_route
to avoid this entirely?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have it working with ReadOnlyNetworkGraph
, FYI.
451c915
to
39af99d
Compare
@@ -460,7 +460,7 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) { | |||
final_cltv_expiry_delta: 42, | |||
}; | |||
let random_seed_bytes: [u8; 32] = keys_manager.get_secure_random_bytes(); | |||
let route = match find_route(&our_id, ¶ms, &network_graph, None, Arc::clone(&logger), &scorer, &random_seed_bytes) { | |||
let route = match find_route(&our_id, ¶ms, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &random_seed_bytes) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
great idea!
@@ -30,10 +30,12 @@ | |||
//! use bitcoin::blockdata::constants::genesis_block; | |||
//! use bitcoin::Network; | |||
//! use lightning::routing::gossip::NetworkGraph; | |||
//! use lightning::util::test_utils::TestLogger; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should the documentation be relying on a test utility?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a hidden FakeLogger
definition and instantiation. Let me know if you prefer something else.
>( | ||
persister: PS, event_handler: EH, chain_monitor: M, channel_manager: CM, | ||
p2p_gossip_sync: Option<PGS>, peer_manager: PM, logger: L, scorer: Option<S>, | ||
rapid_gossip_sync: Option<RGS> | ||
gossip_sync: Option<GossipSync<PGS, RGS, G, CA, L>>, peer_manager: PM, logger: L, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should gossip sync still be an option? I don't recall the net graph message handler being an option, however, I guess it could have been an ignoring message handler
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, it was previously an option in case a user wants to delegate to a trusted server for constructing a route. NetGraphMsgHandler
was simply renamed to P2PGossipSync
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe its easier to just have an enum variant for NoGossip
or whatever?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that's a bit cleaner actually
39af99d
to
9de98e3
Compare
P2P(P), | ||
/// Rapid gossip sync from a trusted server. | ||
Rapid(R), | ||
/// No gossip sync. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hm, I actually think an option might convey nullability better than a none, although this definitely takes much less code. However, for people who want to do an initial rapid catch up, but then supplement it with real data as it becomes available, do you think both makes sense?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hm, I actually think an option might convey nullability better than a none, although this definitely takes much less code.
I also kinda imagine it's simpler in the bindings, no?
However, for people who want to do an initial rapid catch up, but then supplement it with real data as it becomes available, do you think both makes sense?
We currently can't really support that - the lightning protocol doesn't have a way of asking for new gossip without missing lots of gossip, so users probably can't really do this.
Feel free to squash at this point, I don't have anything to complain about right now :) |
P2PGossipSync logs before delegating to NetworkGraph in its EventHandler. In order to share this handling with RapidGossipSync, NetworkGraph needs to take a logger so that it can implement EventHandler instead.
Instead of implementing EventHandler for P2PGossipSync, implement it on NetworkGraph. This allows RapidGossipSync to handle events, too, by delegating to its NetworkGraph.
BackgroundProcessor can take an optional P2PGossipSync and an optional RapidGossipSync, but doing so may be easy to misuse. Each has a reference to a NetworkGraph, which could be different between the two, but only one is actually used. Instead, allow passing one object wrapped in a GossipSync enum. Also, fix a bug where the NetworkGraph is not persisted on shutdown if only a RapidGossipSync is given.
498ae1b
to
c032e28
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is fine for release, but would be good to drop the unnecessary Arc in fuzzing in a followup.
let block_hash = bitcoin::BlockHash::default(); | ||
let network_graph = lightning::routing::gossip::NetworkGraph::new(block_hash); | ||
let logger: Arc<dyn Logger> = Arc::new(test_logger::TestLogger::new("".to_owned(), out)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for dyn or Arc here?
@@ -2380,7 +2366,9 @@ mod tests { | |||
assert!(!network_graph.read_only().nodes().is_empty()); | |||
assert!(!network_graph.read_only().channels().is_empty()); | |||
network_graph.write(&mut w).unwrap(); | |||
assert!(<NetworkGraph>::read(&mut io::Cursor::new(&w.0)).unwrap() == network_graph); | |||
|
|||
let logger = Arc::new(test_utils::TestLogger::new()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: here and the next few tests: no need for Arcs, not that it matters in tests here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's actually needed here because of the later assertion against the NetworkGraph<Arg<test_utils::TestLogger>>
returned by create_network_graph
. I guess using Arc
was a convenience to avoid passing or returning a TestLogger
to/from that function, though an Rc
would have sufficed.
}, | ||
impl<L: Deref> EventHandler for NetworkGraph<L> where L::Target: Logger { | ||
fn handle_event(&self, event: &Event) { | ||
if let Event::PaymentPathFailed { payment_hash: _, rejected_by_dest: _, network_update, .. } = event { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lol not sure why it was there before but we don't need the field: _
crap if we also have a ..
at the end.
/// If rapid gossip sync is meant to run at startup, pass an optional [`RapidGossipSync`] | ||
/// to `rapid_gossip_sync` to indicate to [`BackgroundProcessor`] not to prune the | ||
/// [`NetworkGraph`] instance until the [`RapidGossipSync`] instance completes its first sync. | ||
/// If rapid gossip sync is meant to run at startup, pass a [`RapidGossipSync`] to `gossip_sync` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe via gossip_sync
instead of to gossip_sync
?
Opened #1541 with follow-ups. |
BackgroundProcessor
can take an optionalP2PGossipSync
and an optionalRapidGossipSync
, but doing so may be easy to misuse. Each has a reference to aNetworkGraph
, which could be different between the two, but only one is actually used.Instead, allow passing one object wrapped in a
GossipSync
enum. Also, fix a bug where theNetworkGraph
is not persisted on shutdown if only aRapidGossipSync
is given.