mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-02-22 22:45:27 +01:00
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>
This commit is contained in:
parent
45381bba33
commit
fd2d74aa9b
6 changed files with 55 additions and 4 deletions
|
@ -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 */
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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);
|
||||
|
||||
/**
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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…
Add table
Reference in a new issue