diff --git a/gossipd/gossipd.c b/gossipd/gossipd.c index fd0a70627d5a..5eeb1fc51994 100644 --- a/gossipd/gossipd.c +++ b/gossipd/gossipd.c @@ -747,6 +747,42 @@ static void gossip_refresh_network(struct daemon *daemon) route_prune(daemon->rstate); } +static void tell_master_local_cupdates(struct daemon *daemon) +{ + struct chan_map_iter i; + struct chan *c; + struct node *me; + + me = get_node(daemon->rstate, &daemon->id); + if (!me) + return; + + for (c = first_chan(me, &i); c; c = next_chan(me, &i)) { + struct half_chan *hc; + int direction; + const u8 *cupdate; + + /* We don't provide update_channel for unannounced channels */ + if (!is_chan_public(c)) + continue; + + if (!local_direction(daemon->rstate, c, &direction)) + continue; + + hc = &c->half[direction]; + if (!is_halfchan_defined(hc)) + continue; + + cupdate = gossip_store_get(tmpctx, + daemon->rstate->gs, + hc->bcast.index); + daemon_conn_send(daemon->master, + take(towire_gossipd_init_cupdate(NULL, + &c->scid, + cupdate))); + } +} + /* Disables all channels connected to our node. */ static void gossip_disable_local_channels(struct daemon *daemon) { @@ -851,6 +887,10 @@ static void gossip_init(struct daemon *daemon, const u8 *msg) maybe_send_query_responses, daemon); tal_add_destructor(daemon->connectd, master_or_connectd_gone); + /* Tell it about all our local (public) channel_update messages, + * so it doesn't unnecessarily regenerate them. */ + tell_master_local_cupdates(daemon); + /* OK, we are ready. */ daemon_conn_send(daemon->master, take(towire_gossipd_init_reply(NULL))); @@ -1143,6 +1183,7 @@ static struct io_plan *recv_req(struct io_conn *conn, #endif /* !DEVELOPER */ /* We send these, we don't receive them */ + case WIRE_GOSSIPD_INIT_CUPDATE: case WIRE_GOSSIPD_INIT_REPLY: case WIRE_GOSSIPD_GET_TXOUT: case WIRE_GOSSIPD_DEV_MEMLEAK_REPLY: diff --git a/gossipd/gossipd_wire.csv b/gossipd/gossipd_wire.csv index 2e0b47c1fdc9..28397005b6f1 100644 --- a/gossipd/gossipd_wire.csv +++ b/gossipd/gossipd_wire.csv @@ -18,6 +18,12 @@ msgdata,gossipd_init,dev_fast_gossip,bool, msgdata,gossipd_init,dev_fast_gossip_prune,bool, msgdata,gossipd_init,ip_discovery,u32, +# Gossipd tells us all our public channel_updates before init_reply. +msgtype,gossipd_init_cupdate,3101 +msgdata,gossipd_init_cupdate,scid,short_channel_id, +msgdata,gossipd_init_cupdate,len,u16, +msgdata,gossipd_init_cupdate,cupdate,u8,len + msgtype,gossipd_init_reply,3100 # In developer mode, we can mess with time. diff --git a/lightningd/gossip_control.c b/lightningd/gossip_control.c index f576f07c60db..7b2779d490cb 100644 --- a/lightningd/gossip_control.c +++ b/lightningd/gossip_control.c @@ -109,6 +109,33 @@ static void get_txout(struct subd *gossip, const u8 *msg) } } +static void handle_init_cupdate(struct lightningd *ld, const u8 *msg) +{ + struct short_channel_id scid; + u8 *update; + struct channel *channel; + + if (!fromwire_gossipd_init_cupdate(msg, msg, &scid, &update)) { + fatal("Gossip gave bad GOSSIPD_INIT_CUPDATE %s", + tal_hex(msg, msg)); + } + + /* In theory this could vanish before gossipd gets around to telling + * us. */ + channel = any_channel_by_scid(ld, &scid, true); + if (!channel) { + log_unusual(ld->log, "init_cupdate for bad scid %s", + type_to_string(tmpctx, struct short_channel_id, + &scid)); + return; + } + + /* This should only happen on initialization, *but* gossipd also + * disabled channels on startup, so that can set this first. */ + if (!channel->channel_update) + channel->channel_update = tal_steal(channel, update); +} + static void handle_local_channel_update(struct lightningd *ld, const u8 *msg) { struct short_channel_id scid; @@ -177,6 +204,9 @@ static unsigned gossip_msg(struct subd *gossip, const u8 *msg, const int *fds) case WIRE_GOSSIPD_DISCOVERED_IP: break; + case WIRE_GOSSIPD_INIT_CUPDATE: + handle_init_cupdate(gossip->ld, msg); + break; case WIRE_GOSSIPD_GET_TXOUT: get_txout(gossip, msg); break;