committed by
neil saitug
7 changed files with 203 additions and 118 deletions
@ -0,0 +1,140 @@ |
|||||
|
/* This contains the code which actively seeks out gossip from peers */ |
||||
|
#include <bitcoin/short_channel_id.h> |
||||
|
#include <ccan/list/list.h> |
||||
|
#include <ccan/tal/tal.h> |
||||
|
#include <common/status.h> |
||||
|
#include <common/timeout.h> |
||||
|
#include <common/type_to_string.h> |
||||
|
#include <gossipd/gossipd.h> |
||||
|
#include <gossipd/queries.h> |
||||
|
#include <gossipd/seeker.h> |
||||
|
|
||||
|
/* Gossip we're seeking at the moment. */ |
||||
|
struct seeker { |
||||
|
/* Do we think we're missing gossip? Contains timer to re-check */ |
||||
|
struct oneshot *gossip_missing; |
||||
|
|
||||
|
/* Channels we've heard about, but don't know. */ |
||||
|
struct short_channel_id *unknown_scids; |
||||
|
}; |
||||
|
|
||||
|
struct seeker *new_seeker(struct daemon *daemon) |
||||
|
{ |
||||
|
struct seeker *seeker = tal(daemon, struct seeker); |
||||
|
seeker->gossip_missing = NULL; |
||||
|
seeker->unknown_scids = tal_arr(seeker, struct short_channel_id, 0); |
||||
|
|
||||
|
return seeker; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/*~ This is a timer, which goes off 10 minutes after the last time we noticed
|
||||
|
* that gossip was missing. */ |
||||
|
static void gossip_not_missing(struct daemon *daemon) |
||||
|
{ |
||||
|
struct seeker *seeker = daemon->seeker; |
||||
|
|
||||
|
/* Corner case: no peers, try again! */ |
||||
|
if (list_empty(&daemon->peers)) |
||||
|
gossip_missing(daemon, daemon->seeker); |
||||
|
else { |
||||
|
struct peer *peer; |
||||
|
|
||||
|
seeker->gossip_missing = tal_free(seeker->gossip_missing); |
||||
|
status_info("We seem to be caught up on gossip messages"); |
||||
|
/* Free any lagging/stale unknown scids. */ |
||||
|
seeker->unknown_scids = tal_free(seeker->unknown_scids); |
||||
|
|
||||
|
/* Reset peers we marked as HIGH */ |
||||
|
list_for_each(&daemon->peers, peer, list) { |
||||
|
if (peer->gossip_level != GOSSIP_HIGH) |
||||
|
continue; |
||||
|
if (!peer->gossip_queries_feature) |
||||
|
continue; |
||||
|
peer->gossip_level = peer_gossip_level(daemon, true); |
||||
|
setup_gossip_range(peer); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
static bool peer_is_not_gossip_high(const struct peer *peer) |
||||
|
{ |
||||
|
return peer->gossip_level != GOSSIP_HIGH; |
||||
|
} |
||||
|
|
||||
|
/* We've found gossip is missing. */ |
||||
|
void gossip_missing(struct daemon *daemon, struct seeker *seeker) |
||||
|
{ |
||||
|
if (!seeker->gossip_missing) { |
||||
|
status_info("We seem to be missing gossip messages"); |
||||
|
/* FIXME: we could use query_channel_range. */ |
||||
|
/* Make some peers gossip harder. */ |
||||
|
for (size_t i = 0; i < 3; i++) { |
||||
|
struct peer *peer = random_peer(daemon, |
||||
|
peer_is_not_gossip_high); |
||||
|
|
||||
|
if (!peer) |
||||
|
break; |
||||
|
|
||||
|
status_info("%s: gossip harder!", |
||||
|
type_to_string(tmpctx, struct node_id, |
||||
|
&peer->id)); |
||||
|
peer->gossip_level = GOSSIP_HIGH; |
||||
|
setup_gossip_range(peer); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
tal_free(seeker->gossip_missing); |
||||
|
/* Check again in 10 minutes. */ |
||||
|
seeker->gossip_missing = new_reltimer(&daemon->timers, daemon, |
||||
|
time_from_sec(600), |
||||
|
gossip_not_missing, daemon); |
||||
|
} |
||||
|
|
||||
|
bool remove_unknown_scid(struct seeker *seeker, |
||||
|
const struct short_channel_id *scid) |
||||
|
{ |
||||
|
for (size_t i = 0; i < tal_count(seeker->unknown_scids); i++) { |
||||
|
if (short_channel_id_eq(&seeker->unknown_scids[i], scid)) { |
||||
|
tal_arr_remove(&seeker->unknown_scids, i); |
||||
|
return true; |
||||
|
} |
||||
|
} |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
bool seeker_gossip(const struct seeker *seeker) |
||||
|
{ |
||||
|
return seeker->gossip_missing != NULL; |
||||
|
} |
||||
|
|
||||
|
bool add_unknown_scid(struct seeker *seeker, |
||||
|
const struct short_channel_id *scid) |
||||
|
{ |
||||
|
/* Don't go overboard if we're already asking for a lot. */ |
||||
|
if (tal_count(seeker->unknown_scids) > 1000) |
||||
|
return false; |
||||
|
|
||||
|
/* Check we're not already getting this one. */ |
||||
|
for (size_t i = 0; i < tal_count(seeker->unknown_scids); i++) |
||||
|
if (short_channel_id_eq(&seeker->unknown_scids[i], scid)) |
||||
|
return false; |
||||
|
|
||||
|
tal_arr_expand(&seeker->unknown_scids, *scid); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
/* This peer told us about an update to an unknown channel. Ask it for a
|
||||
|
* channel_announcement. */ |
||||
|
void query_unknown_channel(struct daemon *daemon, |
||||
|
struct peer *peer, |
||||
|
const struct short_channel_id *id) |
||||
|
{ |
||||
|
/* Too many, or duplicate? */ |
||||
|
if (!add_unknown_scid(daemon->seeker, id)) |
||||
|
return; |
||||
|
|
||||
|
/* This is best effort: if peer is busy, we'll try next time. */ |
||||
|
query_short_channel_ids(daemon, peer, daemon->seeker->unknown_scids, |
||||
|
NULL); |
||||
|
} |
@ -0,0 +1,24 @@ |
|||||
|
#ifndef LIGHTNING_GOSSIPD_SEEKER_H |
||||
|
#define LIGHTNING_GOSSIPD_SEEKER_H |
||||
|
#include "config.h" |
||||
|
|
||||
|
struct daemon; |
||||
|
struct peer; |
||||
|
struct short_channel_id; |
||||
|
|
||||
|
struct seeker *new_seeker(struct daemon *daemon); |
||||
|
|
||||
|
void gossip_missing(struct daemon *daemon, struct seeker *seeker); |
||||
|
|
||||
|
void query_unknown_channel(struct daemon *daemon, |
||||
|
struct peer *peer, |
||||
|
const struct short_channel_id *id); |
||||
|
|
||||
|
bool remove_unknown_scid(struct seeker *seeker, |
||||
|
const struct short_channel_id *scid); |
||||
|
bool add_unknown_scid(struct seeker *seeker, |
||||
|
const struct short_channel_id *scid); |
||||
|
|
||||
|
bool seeker_gossip(const struct seeker *seeker); |
||||
|
|
||||
|
#endif /* LIGHTNING_GOSSIPD_SEEKER_H */ |
Loading…
Reference in new issue