mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-19 05:44:12 +01:00
gossipd: query unknown short_channel_ids, note if they were really missing.
The first sign that we're missing gossip is that we get a channel_update for an unknown channel. The peer might be wrong (or lying), but if it turns out to be a real channel, we were definitely missing something. This patch does two things: queries when we get an unknown channel_update, and then notes that a channel_announcement was from such an update when it's finally processed. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
18069ab3da
commit
b9053767e7
@ -116,6 +116,9 @@ struct daemon {
|
||||
|
||||
/* Do we think we're missing gossip? */
|
||||
bool gossip_missing;
|
||||
|
||||
/* Channels we've heard about, but don't know. */
|
||||
struct short_channel_id *unknown_scids;
|
||||
};
|
||||
|
||||
/* This represents each peer we're gossiping with */
|
||||
@ -572,6 +575,27 @@ 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. */
|
||||
static 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, true);
|
||||
}
|
||||
|
||||
/*~Routines to handle gossip messages from peer, forwarded by subdaemons.
|
||||
*-----------------------------------------------------------------------
|
||||
*
|
||||
@ -593,7 +617,9 @@ static const u8 *handle_channel_announcement_msg(struct peer *peer,
|
||||
const struct short_channel_id *scid;
|
||||
const u8 *err;
|
||||
|
||||
/* If it's OK, tells us the short_channel_id to lookup */
|
||||
/* If it's OK, tells us the short_channel_id to lookup; it notes
|
||||
* if this is the unknown channel the peer was looking for (in
|
||||
* which case, it frees and NULLs that ptr) */
|
||||
err = handle_channel_announcement(peer->daemon->rstate, msg, &scid);
|
||||
if (err)
|
||||
return err;
|
||||
@ -605,11 +631,18 @@ static const u8 *handle_channel_announcement_msg(struct peer *peer,
|
||||
|
||||
static u8 *handle_channel_update_msg(struct peer *peer, const u8 *msg)
|
||||
{
|
||||
struct short_channel_id unknown_scid;
|
||||
/* Hand the channel_update to the routing code */
|
||||
u8 *err = handle_channel_update(peer->daemon->rstate, msg, "subdaemon",
|
||||
NULL);
|
||||
if (err)
|
||||
u8 *err;
|
||||
|
||||
unknown_scid.u64 = 0;
|
||||
err = handle_channel_update(peer->daemon->rstate, msg, "subdaemon",
|
||||
&unknown_scid);
|
||||
if (err) {
|
||||
if (unknown_scid.u64 != 0)
|
||||
query_unknown_channel(peer->daemon, peer, &unknown_scid);
|
||||
return err;
|
||||
}
|
||||
|
||||
/*~ As a nasty compromise in the spec, we only forward channel_announce
|
||||
* once we have a channel_update; the channel isn't *usable* for
|
||||
@ -2571,12 +2604,27 @@ static struct io_plan *handle_txout_reply(struct io_conn *conn,
|
||||
struct short_channel_id scid;
|
||||
u8 *outscript;
|
||||
struct amount_sat sat;
|
||||
bool was_unknown;
|
||||
|
||||
if (!fromwire_gossip_get_txout_reply(msg, msg, &scid, &sat, &outscript))
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/* Outscript is NULL if it's not an unspent output */
|
||||
handle_pending_cannouncement(daemon->rstate, &scid, sat, outscript);
|
||||
if (handle_pending_cannouncement(daemon->rstate, &scid, sat, outscript)
|
||||
&& was_unknown) {
|
||||
/* It was real: we're missing gossip. */
|
||||
gossip_missing(daemon);
|
||||
}
|
||||
|
||||
/* Anywhere we might have announced a channel, we check if it's time to
|
||||
* announce ourselves (ie. if we just announced our own first channel) */
|
||||
@ -2840,7 +2888,8 @@ int main(int argc, char *argv[])
|
||||
|
||||
daemon = tal(NULL, struct daemon);
|
||||
list_head_init(&daemon->peers);
|
||||
daemon->gossip_missing = false;
|
||||
daemon->unknown_scids = tal_arr(daemon, struct short_channel_id, 0);
|
||||
daemon->gossip_missing = NULL;
|
||||
|
||||
/* Note the use of time_mono() here. That's a monotonic clock, which
|
||||
* is really useful: it can only be used to measure relative events
|
||||
|
Loading…
Reference in New Issue
Block a user