gossipd: use timestamp information to detect stale scids.
If we have nothing better to do, ask about stale channels. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
af3bc4d11f
commit
918478b0ef
|
@ -42,6 +42,9 @@ enum seeker_state {
|
|||
|
||||
/* Asking a peer for unknown scids. */
|
||||
ASKING_FOR_UNKNOWN_SCIDS,
|
||||
|
||||
/* Asking a peer for stale scids. */
|
||||
ASKING_FOR_STALE_SCIDS,
|
||||
};
|
||||
|
||||
/* Passthrough helper for HTABLE_DEFINE_TYPE */
|
||||
|
@ -283,19 +286,20 @@ static void scid_query_done(struct peer *peer, bool complete)
|
|||
probe_random_scids(seeker, false);
|
||||
}
|
||||
|
||||
static void seek_any_unknown_scids(struct seeker *seeker)
|
||||
/* Returns true if there were scids to seek. */
|
||||
static bool seek_any_unknown_scids(struct seeker *seeker)
|
||||
{
|
||||
struct peer *peer;
|
||||
struct short_channel_id *scids;
|
||||
|
||||
/* Nothing we need to know about? */
|
||||
if (scid_map_count(&seeker->unknown_scids) == 0)
|
||||
return;
|
||||
return false;
|
||||
|
||||
/* No peers can answer? Try again later. */
|
||||
peer = random_peer(seeker->daemon, peer_can_take_scid_query);
|
||||
if (!peer)
|
||||
return;
|
||||
return false;
|
||||
|
||||
set_state(seeker, ASKING_FOR_UNKNOWN_SCIDS);
|
||||
selected_peer(seeker, peer);
|
||||
|
@ -306,6 +310,66 @@ static void seek_any_unknown_scids(struct seeker *seeker)
|
|||
status_failed(STATUS_FAIL_INTERNAL_ERROR,
|
||||
"seeker: quering %zu scids is too many?",
|
||||
tal_count(scids));
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Turns stale_scid_map into two arrays, and removes from map */
|
||||
static struct short_channel_id *stale_scids_remove(const tal_t *ctx,
|
||||
struct seeker *seeker,
|
||||
u8 **query_flags)
|
||||
{
|
||||
struct stale_scid_map *map = &seeker->stale_scids;
|
||||
struct short_channel_id *scids;
|
||||
const struct stale_scid *s;
|
||||
size_t i, max;
|
||||
struct stale_scid_map_iter it;
|
||||
|
||||
/* Marshal into an array: we can fit 7000 comfortably (8 byte scid, 1 byte flag). */
|
||||
if (stale_scid_map_count(map) < 7000)
|
||||
max = stale_scid_map_count(map);
|
||||
else
|
||||
max = 7000;
|
||||
|
||||
scids = tal_arr(ctx, struct short_channel_id, max);
|
||||
*query_flags = tal_arr(ctx, u8, max);
|
||||
|
||||
for (i = 0, s = stale_scid_map_first(map, &it); i < max; i++) {
|
||||
scids[i] = s->scid;
|
||||
(*query_flags)[i] = s->query_flag;
|
||||
stale_scid_map_del(map, s);
|
||||
tal_free(s);
|
||||
}
|
||||
assert(i == tal_count(scids));
|
||||
return scids;
|
||||
}
|
||||
|
||||
static bool seek_any_stale_scids(struct seeker *seeker)
|
||||
{
|
||||
struct peer *peer;
|
||||
struct short_channel_id *scids;
|
||||
u8 *query_flags;
|
||||
|
||||
/* Nothing we need to know about? */
|
||||
if (stale_scid_map_count(&seeker->stale_scids) == 0)
|
||||
return false;
|
||||
|
||||
/* No peers can answer? Try again later. */
|
||||
peer = random_peer(seeker->daemon, peer_can_take_scid_query);
|
||||
if (!peer)
|
||||
return false;
|
||||
|
||||
set_state(seeker, ASKING_FOR_STALE_SCIDS);
|
||||
selected_peer(seeker, peer);
|
||||
|
||||
/* This is best-effort, so this consumes them as well. */
|
||||
scids = stale_scids_remove(tmpctx, seeker, &query_flags);
|
||||
|
||||
if (!query_short_channel_ids(seeker->daemon, peer, scids, query_flags,
|
||||
scid_query_done))
|
||||
status_failed(STATUS_FAIL_INTERNAL_ERROR,
|
||||
"seeker: quering %zu scids is too many?",
|
||||
tal_count(scids));
|
||||
return true;
|
||||
}
|
||||
|
||||
static void check_unknown_scid_query(struct seeker *seeker)
|
||||
|
@ -727,6 +791,25 @@ static void check_nannounce_probing(struct seeker *seeker)
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/* Periodic timer to see how our gossip is going. */
|
||||
static void seeker_check(struct seeker *seeker)
|
||||
|
@ -746,6 +829,9 @@ static void seeker_check(struct seeker *seeker)
|
|||
case ASKING_FOR_UNKNOWN_SCIDS:
|
||||
check_unknown_scid_query(seeker);
|
||||
break;
|
||||
case ASKING_FOR_STALE_SCIDS:
|
||||
check_stale_scid_query(seeker);
|
||||
break;
|
||||
case PROBING_NANNOUNCES_NEED_PEER:
|
||||
peer_gossip_probe_nannounces(seeker);
|
||||
break;
|
||||
|
@ -753,7 +839,8 @@ static void seeker_check(struct seeker *seeker)
|
|||
check_nannounce_probing(seeker);
|
||||
break;
|
||||
case NORMAL:
|
||||
seek_any_unknown_scids(seeker);
|
||||
if (!seek_any_unknown_scids(seeker))
|
||||
seek_any_stale_scids(seeker);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -789,6 +876,7 @@ void seeker_setup_peer_gossip(struct seeker *seeker, struct peer *peer)
|
|||
case PROBING_NANNOUNCES:
|
||||
case NORMAL:
|
||||
case ASKING_FOR_UNKNOWN_SCIDS:
|
||||
case ASKING_FOR_STALE_SCIDS:
|
||||
normal_gossip_start(seeker, peer);
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue