Browse Source

gossipd: simplify seeker state machine.

We eliminate the "need peer" states and instead check if the
random_peer_softref has been cleared.

We can also unify our restart handlers for all these cases; even the
probe_scids case, by giving gossip credit for the scids as they come
in (at a discount, since scids are 8 bytes vs the ~200 bytes for
normal gossip messages).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
travis-debug
Rusty Russell 5 years ago
committed by neil saitug
parent
commit
869b5e40b5
  1. 6
      gossipd/gossipd.c
  2. 2
      gossipd/gossipd.h
  3. 4
      gossipd/queries.c
  4. 4
      gossipd/routing.c
  5. 170
      gossipd/seeker.c
  6. 2
      gossipd/test/run-bench-find_route.c
  7. 3
      gossipd/test/run-crc32_of_update.c
  8. 3
      gossipd/test/run-extended-info.c
  9. 2
      gossipd/test/run-find_route-specific.c
  10. 2
      gossipd/test/run-find_route.c
  11. 2
      gossipd/test/run-overlong.c
  12. 2
      gossipd/test/run-txout_failure.c

6
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

2
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,

4
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,

4
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;
}

170
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,

2
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,

3
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)

3
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)

2
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,

2
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,

2
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,

2
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,

Loading…
Cancel
Save