diff --git a/daemon/p2p_announce.c b/daemon/p2p_announce.c index 50b23faa7..08e5bb0e4 100644 --- a/daemon/p2p_announce.c +++ b/daemon/p2p_announce.c @@ -113,8 +113,8 @@ static bool add_channel_direction(struct lightningd_state *dstate, const struct pubkey *from, const struct pubkey *to, const int direction, - const struct channel_id *channel_id - ) + const struct channel_id *channel_id, + const u8 *announcement) { struct node_connection *c = get_connection(dstate, from, to); if (c){ @@ -126,10 +126,13 @@ static bool add_channel_direction(struct lightningd_state *dstate, }else if(get_connection_by_cid(dstate, channel_id, direction)) { return false; } - half_add_connection(dstate, - from, - to, - channel_id, direction); + + c = half_add_connection(dstate, from, to, channel_id, direction); + + /* Remember the announcement so we can forward it to new peers */ + tal_free(c->channel_announcement); + c->channel_announcement = tal_dup_arr(c, u8, announcement, + tal_count(announcement), 0); return true; } @@ -145,29 +148,32 @@ void handle_channel_announcement( //FIXME(cdecker) Check signatures, when the spec is settled //FIXME(cdecker) Check chain topology for the anchor TX - log_debug(peer->log, "Received channel_announcement for channel %d:%d:%d", - msg->channel_id.blocknum, - msg->channel_id.txnum, - msg->channel_id.outnum + serialized = towire_channel_announcement(msg, msg); + + log_debug(peer->log, + "Received channel_announcement for channel %d:%d:%d", + msg->channel_id.blocknum, + msg->channel_id.txnum, + msg->channel_id.outnum ); + forward |= add_channel_direction(peer->dstate, &msg->node_id_1, - &msg->node_id_2, 0, &msg->channel_id); + &msg->node_id_2, 0, &msg->channel_id, + serialized); forward |= add_channel_direction(peer->dstate, &msg->node_id_2, - &msg->node_id_1, 1, &msg->channel_id); + &msg->node_id_1, 1, &msg->channel_id, + serialized); if (!forward){ log_debug(peer->log, "Not forwarding channel_announcement"); return; } - serialized = towire_channel_announcement(msg, msg); - u8 *tag = tal_arr(msg, u8, 0); towire_channel_id(&tag, &msg->channel_id); - queue_broadcast(peer->dstate, - WIRE_CHANNEL_ANNOUNCEMENT, + queue_broadcast(peer->dstate, WIRE_CHANNEL_ANNOUNCEMENT, 0, /* `channel_announcement`s do not have a timestamp */ - tag, - serialized, peer); + tag, serialized, peer); + tal_free(msg); } @@ -223,6 +229,9 @@ void handle_channel_update(struct peer *peer, const struct msg_channel_update *m msg->timestamp, tag, serialized, peer); + + tal_free(c->channel_update); + c->channel_update = tal_dup_arr(c, u8, serialized, tal_count(serialized), 0); tal_free(msg); } @@ -273,6 +282,8 @@ void handle_node_announcement( msg->timestamp, tag, serialized, peer); + tal_free(node->node_announcement); + node->node_announcement = tal_dup_arr(node, u8, serialized, tal_count(serialized), 0); tal_free(msg); } @@ -325,7 +336,6 @@ static void broadcast_node_announcement(struct lightningd_state *dstate) serialized = towire_node_announcement(msg, msg); broadcast(dstate, WIRE_NODE_ANNOUNCEMENT, serialized, NULL); tal_free(msg); - } static void broadcast_channel_announcement(struct lightningd_state *dstate, struct peer *peer) diff --git a/daemon/peer.c b/daemon/peer.c index 7e891026b..808aee8dd 100644 --- a/daemon/peer.c +++ b/daemon/peer.c @@ -747,6 +747,7 @@ static bool open_wait_pkt_in(struct peer *peer, const Pkt *pkt) peer_open_complete(peer, NULL); set_peer_state(peer, STATE_NORMAL, __func__, true); announce_channel(peer->dstate, peer); + sync_routing_table(peer->dstate, peer); } else { set_peer_state(peer, STATE_OPEN_WAIT_ANCHORDEPTH, __func__, true); @@ -2529,8 +2530,10 @@ static struct io_plan *init_pkt_in(struct io_conn *conn, struct peer *peer) peer_has_connected(peer); - if (state_is_normal(peer->state)) + if (state_is_normal(peer->state)){ announce_channel(peer->dstate, peer); + sync_routing_table(peer->dstate, peer); + } return io_duplex(conn, peer_read_packet(conn, peer, pkt_in), @@ -3317,6 +3320,7 @@ static void peer_depth_ok(struct peer *peer) peer_open_complete(peer, NULL); set_peer_state(peer, STATE_NORMAL, __func__, true); announce_channel(peer->dstate, peer); + sync_routing_table(peer->dstate, peer); break; default: log_broken(peer->log, "%s: state %s", diff --git a/daemon/routing.c b/daemon/routing.c index b260c82d3..b7957c89a 100644 --- a/daemon/routing.c +++ b/daemon/routing.c @@ -2,6 +2,7 @@ #include "lightningd.h" #include "log.h" #include "overflows.h" +#include "packets.h" #include "peer.h" #include "pseudorand.h" #include "routing.h" @@ -67,6 +68,7 @@ struct node *new_node(struct lightningd_state *dstate, n->port = 0; n->alias = NULL; n->hostname = NULL; + n->node_announcement = NULL; node_map_add(dstate->nodes, n); tal_add_destructor(n, destroy_node); @@ -195,6 +197,8 @@ get_or_make_connection(struct lightningd_state *dstate, nc->src = from; nc->dst = to; memset(&nc->channel_id, 0, sizeof(nc->channel_id)); + nc->channel_announcement = NULL; + nc->channel_update = NULL; log_add(dstate->base_log, " = %p (%p->%p)", nc, from, to); /* Hook it into in/out arrays. */ @@ -551,6 +555,26 @@ static void json_add_route(struct command *cmd, command_success(cmd, null_response(cmd)); } +void sync_routing_table(struct lightningd_state *dstate, struct peer *peer) +{ + struct node *n; + struct node_map_iter it; + int i; + struct node_connection *nc; + for (n = node_map_first(dstate->nodes, &it); n; n = node_map_next(dstate->nodes, &it)) { + size_t num_edges = tal_count(n->out); + for (i = 0; i < num_edges; i++) { + nc = n->out[i]; + if (nc->channel_announcement) + queue_pkt_nested(peer, WIRE_CHANNEL_ANNOUNCEMENT, nc->channel_announcement); + if (nc->channel_update) + queue_pkt_nested(peer, WIRE_CHANNEL_UPDATE, nc->channel_update); + } + if (n->node_announcement) + queue_pkt_nested(peer, WIRE_NODE_ANNOUNCEMENT, n->node_announcement); + } +} + const struct json_command dev_add_route_command = { "dev-add-route", json_add_route, diff --git a/daemon/routing.h b/daemon/routing.h index 6f216be55..938ed4f68 100644 --- a/daemon/routing.h +++ b/daemon/routing.h @@ -32,6 +32,10 @@ struct node_connection { /* Flags as specified by the `channel_update`s, among other * things indicated direction wrt the `channel_id` */ u16 flags; + + /* Cached `channel_announcement` and `channel_update` we might forward to new peers*/ + u8 *channel_announcement; + u8 *channel_update; }; struct node { @@ -61,6 +65,9 @@ struct node { /* Color to be used when displaying the name */ u8 rgb_color[3]; + + /* Cached `node_announcement` we might forward to new peers. */ + u8 *node_announcement; }; struct lightningd_state; @@ -125,4 +132,7 @@ struct node_map *empty_node_map(struct lightningd_state *dstate); char *opt_add_route(const char *arg, struct lightningd_state *dstate); +/* Dump all known channels and nodes to the peer. Used when a new connection was established. */ +void sync_routing_table(struct lightningd_state *dstate, struct peer *peer); + #endif /* LIGHTNING_DAEMON_ROUTING_H */