Browse Source

gossipd: defer asking about txouts until we're synced or they're 6 deep.

The first one means we don't discard channels just because we're not
synced, and the second is implied by the spec: don't accept
channel_announcement if the channel isn't 6 deep.  Since LND defers in
such cases, we do too (unless it's newer than the current block, in
which case we simply discard).  Otherwise there's a risk that a slow
node might discard valid gossip.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
travis-debug
Rusty Russell 5 years ago
parent
commit
fd2d74aa9b
  1. 39
      gossipd/gossipd.c
  2. 3
      gossipd/gossipd.h
  3. 14
      gossipd/routing.c
  4. 1
      gossipd/routing.h
  5. 1
      gossipd/test/run-crc32_of_update.c
  6. 1
      gossipd/test/run-extended-info.c

39
gossipd/gossipd.c

@ -547,12 +547,24 @@ static const u8 *handle_channel_announcement_msg(struct peer *peer,
/* 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);
err = handle_channel_announcement(peer->daemon->rstate, msg,
peer->daemon->current_blockheight,
&scid);
if (err)
return err;
else if (scid)
daemon_conn_send(peer->daemon->master,
take(towire_gossip_get_txout(NULL, scid)));
else if (scid) {
/* We give them some grace period, in case we don't know about
* block yet. */
if (peer->daemon->current_blockheight == 0
|| !is_scid_depth_announceable(scid,
peer->daemon->current_blockheight)) {
tal_arr_expand(&peer->daemon->deferred_txouts, *scid);
} else {
daemon_conn_send(peer->daemon->master,
take(towire_gossip_get_txout(NULL,
scid)));
}
}
return NULL;
}
@ -2350,6 +2362,24 @@ static struct io_plan *new_blockheight(struct io_conn *conn,
{
if (!fromwire_gossip_new_blockheight(msg, &daemon->current_blockheight))
master_badmsg(WIRE_GOSSIP_NEW_BLOCKHEIGHT, msg);
/* Check if we can now send any deferred queries. */
for (size_t i = 0; i < tal_count(daemon->deferred_txouts); i++) {
const struct short_channel_id *scid
= &daemon->deferred_txouts[i];
if (!is_scid_depth_announceable(scid,
daemon->current_blockheight))
continue;
/* short_channel_id is deep enough, now ask about it. */
daemon_conn_send(daemon->master,
take(towire_gossip_get_txout(NULL, scid)));
tal_arr_remove(&daemon->deferred_txouts, i);
i--;
}
return daemon_conn_read_next(conn, daemon->master);
}
@ -2885,6 +2915,7 @@ 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->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 */

3
gossipd/gossipd.h

@ -54,6 +54,9 @@ struct daemon {
/* 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;
};
/* Search for a peer. */

14
gossipd/routing.c

@ -1602,6 +1602,7 @@ bool routing_add_channel_announcement(struct routing_state *rstate,
u8 *handle_channel_announcement(struct routing_state *rstate,
const u8 *announce TAKES,
u32 current_blockheight,
const struct short_channel_id **scid)
{
struct pending_cannouncement *pending;
@ -1636,6 +1637,19 @@ u8 *handle_channel_announcement(struct routing_state *rstate,
goto malformed;
}
/* If we know the blockheight, and it's in the future, reject
* out-of-hand. Remember, it should be 6 deep before they tell us
* anyway. */
if (current_blockheight != 0
&& short_channel_id_blocknum(&pending->short_channel_id) > current_blockheight) {
status_debug("Ignoring future channel_announcment for %s"
" (current block %u)",
type_to_string(tmpctx, struct short_channel_id,
&pending->short_channel_id),
current_blockheight);
goto ignored;
}
/* If a prior txout lookup failed there is little point it trying
* again. Just drop the announcement and walk away whistling. Any non-0
* result means this failed before. */

1
gossipd/routing.h

@ -346,6 +346,7 @@ struct chan *new_chan(struct routing_state *rstate,
*/
u8 *handle_channel_announcement(struct routing_state *rstate,
const u8 *announce TAKES,
u32 current_blockheight,
const struct short_channel_id **scid);
/**

1
gossipd/test/run-crc32_of_update.c

@ -177,6 +177,7 @@ const char *got_pong(const u8 *pong UNNEEDED, size_t *num_pings_outstanding UNNE
/* Generated stub for handle_channel_announcement */
u8 *handle_channel_announcement(struct routing_state *rstate UNNEEDED,
const u8 *announce TAKES UNNEEDED,
u32 current_blockheight UNNEEDED,
const struct short_channel_id **scid UNNEEDED)
{ fprintf(stderr, "handle_channel_announcement called!\n"); abort(); }
/* Generated stub for handle_channel_update */

1
gossipd/test/run-extended-info.c

@ -184,6 +184,7 @@ const char *got_pong(const u8 *pong UNNEEDED, size_t *num_pings_outstanding UNNE
/* Generated stub for handle_channel_announcement */
u8 *handle_channel_announcement(struct routing_state *rstate UNNEEDED,
const u8 *announce TAKES UNNEEDED,
u32 current_blockheight UNNEEDED,
const struct short_channel_id **scid UNNEEDED)
{ fprintf(stderr, "handle_channel_announcement called!\n"); abort(); }
/* Generated stub for handle_channel_update */

Loading…
Cancel
Save