From f7cffbad9843f87a8b2827928ea8f49e0477c448 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 8 Oct 2019 12:01:24 +1030 Subject: [PATCH] seeker: try asking peer which gave us unknown data first. This should give more reliable results, though it risks us getting suckered into always consulting the same peer. Signed-off-by: Rusty Russell --- gossipd/seeker.c | 61 ++++++++++++++++++++++++++++++++++++++---------- gossipd/seeker.h | 3 ++- 2 files changed, 51 insertions(+), 13 deletions(-) diff --git a/gossipd/seeker.c b/gossipd/seeker.c index 5894658f4..ec36bc129 100644 --- a/gossipd/seeker.c +++ b/gossipd/seeker.c @@ -98,6 +98,10 @@ struct seeker { /* Peers we've asked to stream us gossip */ struct peer *gossiper_softref[3]; + + /* A peer that told us about unknown gossip. */ + struct peer *preferred_peer_softref; + }; /* Mutual recursion */ @@ -143,6 +147,7 @@ struct seeker *new_seeker(struct daemon *daemon) seeker->random_peer_softref = NULL; for (size_t i = 0; i < ARRAY_SIZE(seeker->gossiper_softref); i++) seeker->gossiper_softref[i] = NULL; + seeker->preferred_peer_softref = NULL; set_state(seeker, STARTING_UP); begin_check_timer(seeker); memleak_add_helper(seeker, memleak_help_seeker); @@ -165,6 +170,30 @@ static bool selected_peer(struct seeker *seeker, struct peer *peer) return true; } +static void set_preferred_peer(struct seeker *seeker, struct peer *peer) +{ + if (seeker->preferred_peer_softref + && seeker->preferred_peer_softref != peer) { + clear_softref(seeker, &seeker->preferred_peer_softref); + set_softref(seeker, &seeker->preferred_peer_softref, peer); + } +} + +/* Get a random peer, but try our preferred peer first, if any. This + * biasses us to the peer that told us of unexpected gossip. */ +static struct peer *random_seeker(struct seeker *seeker, + bool (*check_peer)(const struct peer *peer)) +{ + struct peer *peer = seeker->preferred_peer_softref; + + if (peer && check_peer(peer)) { + clear_softref(seeker, &seeker->random_peer_softref); + return peer; + } + + return random_peer(seeker->daemon, check_peer); +} + static bool peer_made_progress(struct seeker *seeker) { const struct peer *peer = seeker->random_peer_softref; @@ -305,7 +334,7 @@ static bool seek_any_unknown_scids(struct seeker *seeker) return false; /* No peers can answer? Try again later. */ - peer = random_peer(seeker->daemon, peer_can_take_scid_query); + peer = random_seeker(seeker, peer_can_take_scid_query); if (!peer) return false; @@ -362,7 +391,7 @@ static bool seek_any_stale_scids(struct seeker *seeker) return false; /* No peers can answer? Try again later. */ - peer = random_peer(seeker->daemon, peer_can_take_scid_query); + peer = random_seeker(seeker, peer_can_take_scid_query); if (!peer) return false; @@ -508,6 +537,9 @@ static void nodeannounce_query_done(struct peer *peer, bool complete) return; } + /* Since they told us about new announcements, keep asking them. */ + set_preferred_peer(seeker, peer); + /* Double every time. We may skip a few, of course, since map * is changing. */ num_scids *= 2; @@ -532,7 +564,7 @@ static void peer_gossip_probe_nannounces(struct seeker *seeker) { struct peer *peer; - peer = random_peer(seeker->daemon, peer_can_take_scid_query); + peer = random_seeker(seeker, peer_can_take_scid_query); if (!peer) return; selected_peer(seeker, peer); @@ -563,7 +595,8 @@ static bool want_update(struct seeker *seeker, /* They gave us timestamps. Do we want updated versions? */ static void check_timestamps(struct seeker *seeker, struct chan *c, - const struct channel_update_timestamps *ts) + const struct channel_update_timestamps *ts, + struct peer *peer) { struct stale_scid *stale; u8 query_flag = 0; @@ -593,6 +626,7 @@ static void check_timestamps(struct seeker *seeker, stale->scid = c->scid; stale->query_flag = query_flag; stale_scid_map_add(&seeker->stale_scids, stale); + set_preferred_peer(seeker, peer); } } @@ -615,11 +649,11 @@ static void process_scid_probe(struct peer *peer, struct chan *c = get_channel(seeker->daemon->rstate, &scids[i]); if (c) { if (ts) - check_timestamps(seeker, c, ts+i); + check_timestamps(seeker, c, ts+i, peer); continue; } - new_unknown_scids |= add_unknown_scid(seeker, &scids[i]); + new_unknown_scids |= add_unknown_scid(seeker, &scids[i], peer); } /* No new unknown scids, or no more to ask? We give some wiggle @@ -628,7 +662,7 @@ static void process_scid_probe(struct peer *peer, && next_block_range(seeker, number_of_blocks, &first_blocknum, &number_of_blocks)) { /* This must return a peer, since we have the current peer! */ - peer = random_peer(seeker->daemon, peer_can_take_range_query); + peer = random_seeker(seeker, peer_can_take_range_query); assert(peer); selected_peer(seeker, peer); @@ -660,7 +694,7 @@ static void peer_gossip_probe_scids(struct seeker *seeker) { struct peer *peer; - peer = random_peer(seeker->daemon, peer_can_take_range_query); + peer = random_seeker(seeker, peer_can_take_range_query); if (!peer) return; selected_peer(seeker, peer); @@ -712,7 +746,7 @@ static void check_firstpeer(struct seeker *seeker) /* It might have died, pick another. */ if (!peer) { - peer = random_peer(seeker->daemon, peer_has_gossip_queries); + peer = random_seeker(seeker, peer_has_gossip_queries); /* No peer? Wait for a new one to join. */ if (!peer) { status_debug("seeker: no peers, waiting"); @@ -791,7 +825,7 @@ static void maybe_rotate_gossipers(struct seeker *seeker) size_t i; /* If all peers are gossiping, we're done */ - peer = random_peer(seeker->daemon, peer_is_not_gossipper); + peer = random_seeker(seeker, peer_is_not_gossipper); if (!peer) return; @@ -895,7 +929,8 @@ bool remove_unknown_scid(struct seeker *seeker, } bool add_unknown_scid(struct seeker *seeker, - const struct short_channel_id *scid) + const struct short_channel_id *scid, + struct peer *peer) { /* Check we're not already getting this one. */ if (scid_map_get(&seeker->unknown_scids, scid)) @@ -903,6 +938,8 @@ bool add_unknown_scid(struct seeker *seeker, scid_map_add(&seeker->unknown_scids, tal_dup(seeker, struct short_channel_id, scid)); + + set_preferred_peer(seeker, peer); return true; } @@ -913,6 +950,6 @@ void query_unknown_channel(struct daemon *daemon, const struct short_channel_id *id) { /* Too many, or duplicate? */ - if (!add_unknown_scid(daemon->seeker, id)) + if (!add_unknown_scid(daemon->seeker, id, peer)) return; } diff --git a/gossipd/seeker.h b/gossipd/seeker.h index 556178c41..cc78bc6cb 100644 --- a/gossipd/seeker.h +++ b/gossipd/seeker.h @@ -18,5 +18,6 @@ bool remove_unknown_scid(struct seeker *seeker, const struct short_channel_id *scid, bool found); bool add_unknown_scid(struct seeker *seeker, - const struct short_channel_id *scid); + const struct short_channel_id *scid, + struct peer *peer); #endif /* LIGHTNING_GOSSIPD_SEEKER_H */