diff --git a/gossipd/gossipd.c b/gossipd/gossipd.c index e77a31c0c..80deb99fe 100644 --- a/gossipd/gossipd.c +++ b/gossipd/gossipd.c @@ -127,11 +127,11 @@ struct peer *find_peer(struct daemon *daemon, const struct node_id *id) return NULL; } -/* Increment a peer's gossip_counter, if peer not NULL */ -void peer_supplied_good_gossip(struct peer *peer) +/* Increase a peer's gossip_counter, if peer not NULL */ +void peer_supplied_good_gossip(struct peer *peer, size_t amount) { if (peer) - peer->gossip_counter++; + peer->gossip_counter += amount; } /* Queue a gossip message for the peer: the subdaemon on the other end simply diff --git a/gossipd/gossipd.h b/gossipd/gossipd.h index 6cd706910..0773440d3 100644 --- a/gossipd/gossipd.h +++ b/gossipd/gossipd.h @@ -122,7 +122,7 @@ struct peer { struct peer *find_peer(struct daemon *daemon, const struct node_id *id); /* This peer (may be NULL) gave is valid gossip. */ -void peer_supplied_good_gossip(struct peer *peer); +void peer_supplied_good_gossip(struct peer *peer, size_t amount); /* Pick a random peer which passes check_peer */ struct peer *random_peer(struct daemon *daemon, diff --git a/gossipd/queries.c b/gossipd/queries.c index 8408e58d5..0903bd25e 100644 --- a/gossipd/queries.c +++ b/gossipd/queries.c @@ -743,6 +743,10 @@ const u8 *handle_reply_channel_range(struct peer *peer, const u8 *msg) tal_resize(&peer->query_channel_scids, n + tal_count(scids)); memcpy(peer->query_channel_scids + n, scids, tal_bytelen(scids)); + /* Credit peer for answering gossip, so seeker doesn't get upset: + * since scids are only 8 bytes, use a discount over normal gossip. */ + peer_supplied_good_gossip(peer, tal_count(scids) / 20); + /* Add timestamps (if any), or zeroes */ if (tlvs->timestamps_tlv) { ts = decode_channel_update_timestamps(tlvs, diff --git a/gossipd/routing.c b/gossipd/routing.c index ad0132ab4..d68de3765 100644 --- a/gossipd/routing.c +++ b/gossipd/routing.c @@ -2178,7 +2178,7 @@ bool routing_add_channel_update(struct routing_state *rstate, = gossip_store_add(rstate->gs, update, hc->bcast.timestamp, NULL); - peer_supplied_good_gossip(peer); + peer_supplied_good_gossip(peer, 1); } if (uc) { @@ -2497,7 +2497,7 @@ bool routing_add_node_announcement(struct routing_state *rstate, node->bcast.index = gossip_store_add(rstate->gs, msg, node->bcast.timestamp, NULL); - peer_supplied_good_gossip(peer); + peer_supplied_good_gossip(peer, 1); } return true; } diff --git a/gossipd/seeker.c b/gossipd/seeker.c index e5699ebae..d20749231 100644 --- a/gossipd/seeker.c +++ b/gossipd/seeker.c @@ -19,21 +19,12 @@ DEV_FAST_GOSSIP((seeker)->daemon->rstate->dev_fast_gossip, 5, 60) enum seeker_state { - /* First initialized, no peers. */ - STARTING_UP_NEED_PEER, - /* Still streaming gossip from single peer. */ - STARTING_UP_FIRSTPEER, - - /* Probing scids: need peer to check startup really finished. */ - PROBING_SCIDS_NEED_PEER, + STARTING_UP, /* Probing: checking our startup really is finished. */ PROBING_SCIDS, - /* Probing: need peer to check that we have node_announcements. */ - PROBING_NANNOUNCES_NEED_PEER, - /* Probing: check that we have node_announcements. */ PROBING_NANNOUNCES, @@ -110,11 +101,7 @@ struct seeker { /* Mutual recursion */ static void seeker_check(struct seeker *seeker); - -/* If we think we might be missing something, call with true. If we - * think we're caught up, call with false. */ -static void probe_random_scids(struct seeker *seeker, - bool suspect_something_wrong); +static void probe_some_random_scids(struct seeker *seeker); static void begin_check_timer(struct seeker *seeker) { @@ -153,7 +140,8 @@ struct seeker *new_seeker(struct daemon *daemon, u32 timestamp) scid_map_init(&seeker->unknown_scids); stale_scid_map_init(&seeker->stale_scids); seeker->last_gossip_timestamp = timestamp; - set_state(seeker, STARTING_UP_NEED_PEER); + seeker->random_peer_softref = NULL; + set_state(seeker, STARTING_UP); begin_check_timer(seeker); memleak_add_helper(seeker, memleak_help_seeker); return seeker; @@ -283,7 +271,7 @@ static void scid_query_done(struct peer *peer, bool complete) /* Peer completed! OK, start random scid probe in case we're * still missing gossip. */ - probe_random_scids(seeker, false); + probe_some_random_scids(seeker); } /* Returns true if there were scids to seek. */ @@ -372,26 +360,6 @@ static bool seek_any_stale_scids(struct seeker *seeker) return true; } -static void check_unknown_scid_query(struct seeker *seeker) -{ - struct peer *peer = seeker->random_peer_softref; - - /* Did peer die? */ - if (!peer) { - probe_random_scids(seeker, true); - return; - } - - if (!peer_made_progress(seeker)) { - status_unusual("Bad gossip: peer %s has only moved gossip %zu->%zu for scid probe, hanging up on it", - type_to_string(tmpctx, struct node_id, &peer->id), - seeker->prev_gossip_count, peer->gossip_counter); - tal_free(peer); - - probe_random_scids(seeker, true); - } -} - /* Returns true and sets first_blocknum and number_of_blocks if * there's more to find. */ static bool next_block_range(struct seeker *seeker, @@ -533,7 +501,6 @@ static void nodeannounce_query_done(struct peer *peer, bool complete) return; } - set_state(seeker, PROBING_NANNOUNCES_NEED_PEER); peer_gossip_probe_nannounces(seeker); } @@ -646,7 +613,7 @@ static void process_scid_probe(struct peer *peer, } /* Channel probe finished, try asking for 32 unannounced nodes. */ - set_state(seeker, PROBING_NANNOUNCES_NEED_PEER); + set_state(seeker, PROBING_NANNOUNCES); seeker->nannounce_offset = 0; if (!get_unannounced_nodes(seeker, seeker->daemon->rstate, @@ -680,13 +647,8 @@ static void peer_gossip_probe_scids(struct seeker *seeker) set_state(seeker, PROBING_SCIDS); } -static void probe_random_scids(struct seeker *seeker, - bool suspect_something_wrong) +static void probe_random_scids(struct seeker *seeker, size_t num_blocks) { - /* We usually get a channel per block, so this covers a fair - bit of ground */ - size_t num_blocks = suspect_something_wrong ? 1008 : 64; - if (seeker->daemon->current_blockheight < num_blocks) { seeker->scid_probe_start = 0; seeker->scid_probe_end = seeker->daemon->current_blockheight; @@ -698,12 +660,23 @@ static void probe_random_scids(struct seeker *seeker, = seeker->scid_probe_start + num_blocks - 1; } - set_state(seeker, PROBING_SCIDS_NEED_PEER); + set_state(seeker, PROBING_SCIDS); seeker->nannounce_scids = NULL; seeker->nannounce_offset = 0; peer_gossip_probe_scids(seeker); } +/* We usually get a channel per block, so these cover a fair bit of ground */ +static void probe_some_random_scids(struct seeker *seeker) +{ + return probe_random_scids(seeker, 64); +} + +static void probe_many_random_scids(struct seeker *seeker) +{ + return probe_random_scids(seeker, 1008); +} + static void check_firstpeer(struct seeker *seeker) { struct chan *c; @@ -712,12 +685,10 @@ static void check_firstpeer(struct seeker *seeker) /* It might have died, pick another. */ if (!peer) { - status_debug("seeker: startup peer died, re-choosing"); peer = random_peer(seeker->daemon, peer_has_gossip_queries); /* No peer? Wait for a new one to join. */ if (!peer) { status_debug("seeker: no peers, waiting"); - set_state(seeker, STARTING_UP_NEED_PEER); return; } @@ -748,33 +719,18 @@ static void check_firstpeer(struct seeker *seeker) seeker->scid_probe_start = 0; } seeker->scid_probe_end = seeker->daemon->current_blockheight; - set_state(seeker, PROBING_SCIDS_NEED_PEER); + set_state(seeker, PROBING_SCIDS); peer_gossip_probe_scids(seeker); } -static void check_scid_probing(struct seeker *seeker) +static void check_probe(struct seeker *seeker, + void (*restart)(struct seeker *seeker)) { - /* FIXME: Time them out of they don't respond to gossip */ struct peer *peer = seeker->random_peer_softref; /* It might have died, pick another. */ if (!peer) { - status_debug("seeker: scid probing peer died, re-choosing"); - set_state(seeker, PROBING_SCIDS_NEED_PEER); - peer_gossip_probe_scids(seeker); - return; - } -} - -static void check_nannounce_probing(struct seeker *seeker) -{ - struct peer *peer = seeker->random_peer_softref; - - /* It might have died, pick another. */ - if (!peer) { - status_debug("seeker: nannounce probing peer died, re-choosing"); - set_state(seeker, PROBING_NANNOUNCES_NEED_PEER); - peer_gossip_probe_nannounces(seeker); + restart(seeker); return; } @@ -782,61 +738,31 @@ static void check_nannounce_probing(struct seeker *seeker) if (peer_made_progress(seeker)) return; - status_unusual("Peer %s has only moved gossip %zu->%zu for nannounce probe, hanging up on it", - type_to_string(tmpctx, struct node_id, &peer->id), - seeker->prev_gossip_count, peer->gossip_counter); + status_debug("Peer %s has only moved gossip %zu->%zu for probe, hanging up on it", + type_to_string(tmpctx, struct node_id, &peer->id), + seeker->prev_gossip_count, peer->gossip_counter); tal_free(peer); - - set_state(seeker, PROBING_NANNOUNCES_NEED_PEER); - peer_gossip_probe_nannounces(seeker); -} - -static void check_stale_scid_query(struct seeker *seeker) -{ - struct peer *peer = seeker->random_peer_softref; - - /* Did peer die? */ - if (!peer) { - probe_random_scids(seeker, true); - return; - } - - if (!peer_made_progress(seeker)) { - status_unusual("Bad gossip: peer %s has only moved gossip %zu->%zu for scid stale probe, hanging up on it", - type_to_string(tmpctx, struct node_id, &peer->id), - seeker->prev_gossip_count, peer->gossip_counter); - tal_free(peer); - - probe_random_scids(seeker, true); - } + restart(seeker); } /* Periodic timer to see how our gossip is going. */ static void seeker_check(struct seeker *seeker) { switch (seeker->state) { - case STARTING_UP_NEED_PEER: - break; - case STARTING_UP_FIRSTPEER: + case STARTING_UP: check_firstpeer(seeker); break; - case PROBING_SCIDS_NEED_PEER: - peer_gossip_probe_scids(seeker); - break; case PROBING_SCIDS: - check_scid_probing(seeker); + check_probe(seeker, peer_gossip_probe_scids); break; case ASKING_FOR_UNKNOWN_SCIDS: - check_unknown_scid_query(seeker); + check_probe(seeker, probe_many_random_scids); break; case ASKING_FOR_STALE_SCIDS: - check_stale_scid_query(seeker); - break; - case PROBING_NANNOUNCES_NEED_PEER: - peer_gossip_probe_nannounces(seeker); + check_probe(seeker, probe_some_random_scids); break; case PROBING_NANNOUNCES: - check_nannounce_probing(seeker); + check_probe(seeker, peer_gossip_probe_nannounces); break; case NORMAL: if (!seek_any_unknown_scids(seeker)) @@ -850,37 +776,39 @@ static void seeker_check(struct seeker *seeker) /* We get this when we have a new peer. */ void seeker_setup_peer_gossip(struct seeker *seeker, struct peer *peer) { + bool have_probing_peer = seeker->random_peer_softref != NULL; + /* Can't do anything useful with these peers. */ if (!peer->gossip_queries_feature) return; switch (seeker->state) { - case STARTING_UP_NEED_PEER: - peer_gossip_startup(seeker, peer); - set_state(seeker, STARTING_UP_FIRSTPEER); - return; - case STARTING_UP_FIRSTPEER: + case STARTING_UP: + if (!have_probing_peer) + peer_gossip_startup(seeker, peer); /* Waiting for seeker_check to release us */ return; /* In these states, we set up peers to stream gossip normally */ - case PROBING_SCIDS_NEED_PEER: - peer_gossip_probe_scids(seeker); - normal_gossip_start(seeker, peer); - return; - case PROBING_NANNOUNCES_NEED_PEER: - peer_gossip_probe_nannounces(seeker); - normal_gossip_start(seeker, peer); - return; case PROBING_SCIDS: + if (!have_probing_peer) + peer_gossip_probe_scids(seeker); + goto start_them_gossiping; + case PROBING_NANNOUNCES: + if (!have_probing_peer) + peer_gossip_probe_nannounces(seeker); + goto start_them_gossiping; + case NORMAL: case ASKING_FOR_UNKNOWN_SCIDS: case ASKING_FOR_STALE_SCIDS: - normal_gossip_start(seeker, peer); - return; + goto start_them_gossiping; } abort(); + +start_them_gossiping: + normal_gossip_start(seeker, peer); } bool remove_unknown_scid(struct seeker *seeker, diff --git a/gossipd/test/run-bench-find_route.c b/gossipd/test/run-bench-find_route.c index 8f072fc40..b7cc22a91 100644 --- a/gossipd/test/run-bench-find_route.c +++ b/gossipd/test/run-bench-find_route.c @@ -55,7 +55,7 @@ bool nannounce_different(struct gossip_store *gs UNNEEDED, const char *onion_type_name(int e UNNEEDED) { fprintf(stderr, "onion_type_name called!\n"); abort(); } /* Generated stub for peer_supplied_good_gossip */ -void peer_supplied_good_gossip(struct peer *peer UNNEEDED) +void peer_supplied_good_gossip(struct peer *peer UNNEEDED, size_t amount UNNEEDED) { fprintf(stderr, "peer_supplied_good_gossip called!\n"); abort(); } /* Generated stub for sanitize_error */ char *sanitize_error(const tal_t *ctx UNNEEDED, const u8 *errmsg UNNEEDED, diff --git a/gossipd/test/run-crc32_of_update.c b/gossipd/test/run-crc32_of_update.c index 7bef1db94..1bd0ad13c 100644 --- a/gossipd/test/run-crc32_of_update.c +++ b/gossipd/test/run-crc32_of_update.c @@ -72,6 +72,9 @@ struct oneshot *new_reltimer_(struct timers *timers UNNEEDED, /* Generated stub for notleak_ */ void *notleak_(const void *ptr UNNEEDED, bool plus_children UNNEEDED) { fprintf(stderr, "notleak_ called!\n"); abort(); } +/* Generated stub for peer_supplied_good_gossip */ +void peer_supplied_good_gossip(struct peer *peer UNNEEDED, size_t amount UNNEEDED) +{ fprintf(stderr, "peer_supplied_good_gossip called!\n"); abort(); } /* Generated stub for queue_peer_from_store */ void queue_peer_from_store(struct peer *peer UNNEEDED, const struct broadcastable *bcast UNNEEDED) diff --git a/gossipd/test/run-extended-info.c b/gossipd/test/run-extended-info.c index ac87a1aab..229a4cfc0 100644 --- a/gossipd/test/run-extended-info.c +++ b/gossipd/test/run-extended-info.c @@ -51,6 +51,9 @@ const u8 *gossip_store_get(const tal_t *ctx UNNEEDED, /* Generated stub for master_badmsg */ void master_badmsg(u32 type_expected UNNEEDED, const u8 *msg) { fprintf(stderr, "master_badmsg called!\n"); abort(); } +/* Generated stub for peer_supplied_good_gossip */ +void peer_supplied_good_gossip(struct peer *peer UNNEEDED, size_t amount UNNEEDED) +{ fprintf(stderr, "peer_supplied_good_gossip called!\n"); abort(); } /* Generated stub for queue_peer_from_store */ void queue_peer_from_store(struct peer *peer UNNEEDED, const struct broadcastable *bcast UNNEEDED) diff --git a/gossipd/test/run-find_route-specific.c b/gossipd/test/run-find_route-specific.c index 505e7bd8d..b5e04ef12 100644 --- a/gossipd/test/run-find_route-specific.c +++ b/gossipd/test/run-find_route-specific.c @@ -44,7 +44,7 @@ bool nannounce_different(struct gossip_store *gs UNNEEDED, const char *onion_type_name(int e UNNEEDED) { fprintf(stderr, "onion_type_name called!\n"); abort(); } /* Generated stub for peer_supplied_good_gossip */ -void peer_supplied_good_gossip(struct peer *peer UNNEEDED) +void peer_supplied_good_gossip(struct peer *peer UNNEEDED, size_t amount UNNEEDED) { fprintf(stderr, "peer_supplied_good_gossip called!\n"); abort(); } /* Generated stub for sanitize_error */ char *sanitize_error(const tal_t *ctx UNNEEDED, const u8 *errmsg UNNEEDED, diff --git a/gossipd/test/run-find_route.c b/gossipd/test/run-find_route.c index 09666e605..f76693fab 100644 --- a/gossipd/test/run-find_route.c +++ b/gossipd/test/run-find_route.c @@ -42,7 +42,7 @@ bool nannounce_different(struct gossip_store *gs UNNEEDED, const char *onion_type_name(int e UNNEEDED) { fprintf(stderr, "onion_type_name called!\n"); abort(); } /* Generated stub for peer_supplied_good_gossip */ -void peer_supplied_good_gossip(struct peer *peer UNNEEDED) +void peer_supplied_good_gossip(struct peer *peer UNNEEDED, size_t amount UNNEEDED) { fprintf(stderr, "peer_supplied_good_gossip called!\n"); abort(); } /* Generated stub for sanitize_error */ char *sanitize_error(const tal_t *ctx UNNEEDED, const u8 *errmsg UNNEEDED, diff --git a/gossipd/test/run-overlong.c b/gossipd/test/run-overlong.c index 07957390f..c136e4ede 100644 --- a/gossipd/test/run-overlong.c +++ b/gossipd/test/run-overlong.c @@ -42,7 +42,7 @@ bool nannounce_different(struct gossip_store *gs UNNEEDED, const char *onion_type_name(int e UNNEEDED) { fprintf(stderr, "onion_type_name called!\n"); abort(); } /* Generated stub for peer_supplied_good_gossip */ -void peer_supplied_good_gossip(struct peer *peer UNNEEDED) +void peer_supplied_good_gossip(struct peer *peer UNNEEDED, size_t amount UNNEEDED) { fprintf(stderr, "peer_supplied_good_gossip called!\n"); abort(); } /* Generated stub for sanitize_error */ char *sanitize_error(const tal_t *ctx UNNEEDED, const u8 *errmsg UNNEEDED, diff --git a/gossipd/test/run-txout_failure.c b/gossipd/test/run-txout_failure.c index 04d16a483..513480760 100644 --- a/gossipd/test/run-txout_failure.c +++ b/gossipd/test/run-txout_failure.c @@ -54,7 +54,7 @@ bool nannounce_different(struct gossip_store *gs UNNEEDED, const char *onion_type_name(int e UNNEEDED) { fprintf(stderr, "onion_type_name called!\n"); abort(); } /* Generated stub for peer_supplied_good_gossip */ -void peer_supplied_good_gossip(struct peer *peer UNNEEDED) +void peer_supplied_good_gossip(struct peer *peer UNNEEDED, size_t amount UNNEEDED) { fprintf(stderr, "peer_supplied_good_gossip called!\n"); abort(); } /* Generated stub for sanitize_error */ char *sanitize_error(const tal_t *ctx UNNEEDED, const u8 *errmsg UNNEEDED,