Browse Source

gossipd: move gossip seeking routines into new file seeker.c

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
travis-debug
Rusty Russell 5 years ago
committed by neil saitug
parent
commit
55323ec385
  1. 3
      gossipd/Makefile
  2. 93
      gossipd/gossipd.c
  3. 21
      gossipd/gossipd.h
  4. 30
      gossipd/queries.c
  5. 10
      gossipd/queries.h
  6. 140
      gossipd/seeker.c
  7. 24
      gossipd/seeker.h

3
gossipd/Makefile

@ -19,7 +19,8 @@ LIGHTNINGD_GOSSIP_HEADERS_WSRC := gossipd/gen_gossip_wire.h \
gossipd/gossip_store.h \
gossipd/queries.h \
gossipd/gossip_generation.h \
gossipd/routing.h
gossipd/routing.h \
gossipd/seeker.h
LIGHTNINGD_GOSSIP_HEADERS := $(LIGHTNINGD_GOSSIP_HEADERS_WSRC) gossipd/broadcast.h
LIGHTNINGD_GOSSIP_SRC := $(LIGHTNINGD_GOSSIP_HEADERS_WSRC:.h=.c)
LIGHTNINGD_GOSSIP_OBJS := $(LIGHTNINGD_GOSSIP_SRC:.c=.o)

93
gossipd/gossipd.c

@ -51,6 +51,7 @@
#include <gossipd/gossipd.h>
#include <gossipd/queries.h>
#include <gossipd/routing.h>
#include <gossipd/seeker.h>
#include <inttypes.h>
#include <lightningd/gossip_msg.h>
#include <netdb.h>
@ -178,7 +179,7 @@ static u32 gossip_start(const struct routing_state *rstate,
* - if the `gossip_queries` feature is negotiated:
* - MUST NOT relay any gossip messages unless explicitly requested.
*/
static void setup_gossip_range(struct peer *peer)
void setup_gossip_range(struct peer *peer)
{
u8 *msg;
@ -557,8 +558,8 @@ done:
}
/* What gossip level do we set for this to meet our target? */
static enum gossip_level peer_gossip_level(const struct daemon *daemon,
bool gossip_queries_feature)
enum gossip_level peer_gossip_level(const struct daemon *daemon,
bool gossip_queries_feature)
{
struct peer *peer;
size_t gossip_levels[ARRAY_SIZE(gossip_level_targets)];
@ -580,7 +581,7 @@ static enum gossip_level peer_gossip_level(const struct daemon *daemon,
gossip_levels[peer->gossip_level]++;
/* If we're missing gossip, try to fill GOSSIP_HIGH */
if (daemon->gossip_missing != NULL)
if (seeker_gossip(daemon->seeker))
glevel = GOSSIP_HIGH;
else
glevel = GOSSIP_MEDIUM;
@ -854,8 +855,8 @@ static void gossip_disable_local_channels(struct daemon *daemon)
local_disable_chan(daemon->rstate, c);
}
static struct peer *random_peer(struct daemon *daemon,
bool (*check_peer)(const struct peer *peer))
struct peer *random_peer(struct daemon *daemon,
bool (*check_peer)(const struct peer *peer))
{
u64 target = UINT64_MAX;
struct peer *best = NULL, *i;
@ -876,70 +877,6 @@ static struct peer *random_peer(struct daemon *daemon,
return best;
}
/* Mutual recursion, so we pre-declare this. */
static void gossip_not_missing(struct daemon *daemon);
static bool peer_is_not_gossip_high(const struct peer *peer)
{
return peer->gossip_level != GOSSIP_HIGH;
}
/*~ We've found gossip is missing. */
static void gossip_missing(struct daemon *daemon)
{
if (!daemon->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 < gossip_level_targets[GOSSIP_HIGH]; 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(daemon->gossip_missing);
/* Check again in 10 minutes. */
daemon->gossip_missing = new_reltimer(&daemon->timers, daemon,
time_from_sec(600),
gossip_not_missing, daemon);
}
/*~ 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)
{
/* Corner case: no peers, try again! */
if (list_empty(&daemon->peers))
gossip_missing(daemon);
else {
struct peer *peer;
daemon->gossip_missing = tal_free(daemon->gossip_missing);
status_info("We seem to be caught up on gossip messages");
/* Free any lagging/stale unknown scids. */
daemon->unknown_scids = tal_free(daemon->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);
}
}
}
/*~ Parse init message from lightningd: starts the daemon properly. */
static struct io_plan *gossip_init(struct io_conn *conn,
struct daemon *daemon,
@ -976,7 +913,7 @@ static struct io_plan *gossip_init(struct io_conn *conn,
timestamp = gossip_store_load(daemon->rstate, daemon->rstate->gs);
/* If gossip_store less than 24 hours old, say we're OK. */
if (timestamp < gossip_time_now(daemon->rstate).ts.tv_sec - 24*3600)
gossip_missing(daemon);
gossip_missing(daemon, daemon->seeker);
/* Now disable all local channels, they can't be connected yet. */
gossip_disable_local_channels(daemon);
@ -1523,21 +1460,14 @@ static struct io_plan *handle_txout_reply(struct io_conn *conn,
master_badmsg(WIRE_GOSSIP_GET_TXOUT_REPLY, msg);
/* Were we looking specifically for this? */
was_unknown = false;
for (size_t i = 0; i < tal_count(daemon->unknown_scids); i++) {
if (short_channel_id_eq(&daemon->unknown_scids[i], &scid)) {
was_unknown = true;
tal_arr_remove(&daemon->unknown_scids, i);
break;
}
}
was_unknown = remove_unknown_scid(daemon->seeker, &scid);
/* Outscript is NULL if it's not an unspent output */
if (handle_pending_cannouncement(daemon, daemon->rstate,
&scid, sat, outscript)
&& was_unknown) {
/* It was real: we're missing gossip. */
gossip_missing(daemon);
gossip_missing(daemon, daemon->seeker);
}
/* Anywhere we might have announced a channel, we check if it's time to
@ -1794,9 +1724,8 @@ int main(int argc, char *argv[])
daemon = tal(NULL, struct daemon);
list_head_init(&daemon->peers);
daemon->unknown_scids = tal_arr(daemon, struct short_channel_id, 0);
daemon->seeker = new_seeker(daemon);
daemon->deferred_txouts = tal_arr(daemon, struct short_channel_id, 0);
daemon->gossip_missing = NULL;
daemon->node_announce_timer = NULL;
daemon->current_blockheight = 0; /* i.e. unknown */

21
gossipd/gossipd.h

@ -16,6 +16,7 @@
struct chan;
struct broadcastable;
struct seeker;
/*~ The core daemon structure: */
struct daemon {
@ -53,17 +54,14 @@ struct daemon {
/* What addresses we can actually announce. */
struct wireaddr *announcable;
/* 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;
/* Timer until we can send a new node_announcement */
struct oneshot *node_announce_timer;
/* Channels we have an announce for, but aren't deep enough. */
struct short_channel_id *deferred_txouts;
/* What, if any, gossip we're seeker from peers. */
struct seeker *seeker;
};
/*~ How gossipy do we ask a peer to be? */
@ -135,6 +133,14 @@ 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);
/* Pick a random peer which passes check_peer */
struct peer *random_peer(struct daemon *daemon,
bool (*check_peer)(const struct peer *peer));
/* Extract gossip level for this peer */
enum gossip_level peer_gossip_level(const struct daemon *daemon,
bool gossip_queries_feature);
/* Queue a gossip message for the peer: the subdaemon on the other end simply
* forwards it to the peer. */
void queue_peer_msg(struct peer *peer, const u8 *msg TAKES);
@ -144,4 +150,7 @@ void queue_peer_msg(struct peer *peer, const u8 *msg TAKES);
void queue_peer_from_store(struct peer *peer,
const struct broadcastable *bcast);
/* Reset gossip range for this peer. */
void setup_gossip_range(struct peer *peer);
#endif /* LIGHTNING_GOSSIPD_GOSSIPD_H */

30
gossipd/queries.c

@ -13,6 +13,7 @@
#include <gossipd/gossipd.h>
#include <gossipd/queries.h>
#include <gossipd/routing.h>
#include <gossipd/seeker.h>
#include <wire/gen_peer_wire.h>
#include <wire/wire.h>
#include <zlib.h>
@ -143,10 +144,10 @@ static UNNEEDED bool encoding_end_external_type(u8 **encoded, u8 *type, size_t m
}
/* Query this peer for these short-channel-ids. */
static bool query_short_channel_ids(struct daemon *daemon,
struct peer *peer,
const struct short_channel_id *scids,
void (*cb)(struct peer *peer, bool complete))
bool query_short_channel_ids(struct daemon *daemon,
struct peer *peer,
const struct short_channel_id *scids,
void (*cb)(struct peer *peer, bool complete))
{
u8 *encoded, *msg;
@ -197,27 +198,6 @@ static bool query_short_channel_ids(struct daemon *daemon,
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)
{
/* Don't go overboard if we're already asking for a lot. */
if (tal_count(daemon->unknown_scids) > 1000)
return;
/* Check we're not already getting this one. */
for (size_t i = 0; i < tal_count(daemon->unknown_scids); i++)
if (short_channel_id_eq(&daemon->unknown_scids[i], id))
return;
tal_arr_expand(&daemon->unknown_scids, *id);
/* This is best effort: if peer is busy, we'll try next time. */
query_short_channel_ids(daemon, peer, daemon->unknown_scids, NULL);
}
/* The peer can ask about an array of short channel ids: we don't assemble the
* reply immediately but process them one at a time in dump_gossip which is
* called when there's nothing more important to send. */

10
gossipd/queries.h

@ -15,10 +15,6 @@ const u8 *handle_reply_short_channel_ids_end(struct peer *peer, const u8 *msg);
const u8 *handle_query_channel_range(struct peer *peer, const u8 *msg);
const u8 *handle_reply_channel_range(struct peer *peer, const u8 *msg);
void query_unknown_channel(struct daemon *daemon,
struct peer *peer,
const struct short_channel_id *id);
/* This called when the peer is idle. */
void maybe_send_query_responses(struct peer *peer);
@ -32,6 +28,12 @@ bool query_channel_range(struct daemon *daemon,
const struct short_channel_id *scids,
bool complete));
/* Ask this peer for info about an array of scids */
bool query_short_channel_ids(struct daemon *daemon,
struct peer *peer,
const struct short_channel_id *scids,
void (*cb)(struct peer *peer, bool complete));
#if DEVELOPER
struct io_plan *query_scids_req(struct io_conn *conn,
struct daemon *daemon,

140
gossipd/seeker.c

@ -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);
}

24
gossipd/seeker.h

@ -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…
Cancel
Save