From 0790d9b52fa9d25bebd71736681e86b8b4d63e6b Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Fri, 2 Feb 2018 19:49:12 +0100 Subject: [PATCH] gossip: Add a map for pending node_announcements We were dropping these on the floor while checking for txout. So now we add a map that holds announcements while we are checking. Signed-off-by: Christian Decker --- gossipd/routing.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++ gossipd/routing.h | 4 +++ 2 files changed, 76 insertions(+) diff --git a/gossipd/routing.c b/gossipd/routing.c index 713015829..995576c79 100644 --- a/gossipd/routing.c +++ b/gossipd/routing.c @@ -53,6 +53,28 @@ struct pending_cannouncement { u32 update_timestamps[2]; }; +struct pending_node_announce { + struct pubkey nodeid; + u8 *node_announcement; + u32 timestamp; +}; + +static const secp256k1_pubkey * +pending_node_announce_keyof(const struct pending_node_announce *a) +{ + return &a->nodeid.pubkey; +} + +static bool pending_node_announce_eq(const struct pending_node_announce *pna, + const secp256k1_pubkey *key) +{ + return structeq(&pna->nodeid.pubkey, key); +} + +HTABLE_DEFINE_TYPE(struct pending_node_announce, pending_node_announce_keyof, + node_map_hash_key, pending_node_announce_eq, + pending_node_map); + /** * routing_channel keeps track of the indices in the broadcast queue * for the corresponding messages. This way we always know exactly @@ -83,6 +105,9 @@ struct routing_state *new_routing_state(const tal_t *ctx, list_head_init(&rstate->pending_cannouncement); uintmap_init(&rstate->channels); + rstate->pending_node_map = tal(ctx, struct pending_node_map); + pending_node_map_init(rstate->pending_node_map); + return rstate; } @@ -596,6 +621,30 @@ void channel_add_connection(struct routing_state *rstate, tal_add_destructor2(nc, remove_connection_from_channel, rstate); } +static void add_pending_node_announcement(struct routing_state *rstate, struct pubkey *nodeid) +{ + struct pending_node_announce *pna = tal(rstate, struct pending_node_announce); + pna->nodeid = *nodeid; + pna->node_announcement = NULL; + pna->timestamp = 0; + pending_node_map_add(rstate->pending_node_map, pna); +} + +static void process_pending_node_announcement(struct routing_state *rstate, + struct pubkey *nodeid) +{ + struct pending_node_announce *pna = pending_node_map_get(rstate->pending_node_map, &nodeid->pubkey); + if (!pna) + return; + + if (pna->node_announcement) { + status_trace("Processing deferred node_announcement for node %s", type_to_string(pna, struct pubkey, nodeid)); + handle_node_announcement(rstate, pna->node_announcement); + } + pending_node_map_del(rstate->pending_node_map, pna); + tal_free(pna); +} + const struct short_channel_id *handle_channel_announcement( struct routing_state *rstate, const u8 *announce TAKES) @@ -697,6 +746,11 @@ const struct short_channel_id *handle_channel_announcement( chan->public = true; uintmap_add(&rstate->channels, scid, chan); + /* Add both endpoints to the pending_node_map so we can stash + * node_announcements while we wait for the txout check */ + add_pending_node_announcement(rstate, &pending->node_id_1); + add_pending_node_announcement(rstate, &pending->node_id_2); + list_add_tail(&rstate->pending_cannouncement, &pending->list); return &pending->short_channel_id; } @@ -791,6 +845,9 @@ bool handle_pending_cannouncement(struct routing_state *rstate, if (pending->updates[1]) handle_channel_update(rstate, pending->updates[1]); + process_pending_node_announcement(rstate, &pending->node_id_1); + process_pending_node_announcement(rstate, &pending->node_id_2); + tal_free(pending); return local && forward; } @@ -1004,8 +1061,23 @@ void handle_node_announcement( tal_free(tmpctx); return; } + node = get_node(rstate, &node_id); + /* Check if we are currently verifying the txout for a + * matching channel */ + struct pending_node_announce *pna = pending_node_map_get(rstate->pending_node_map, &node_id.pubkey); + if (!node && pna) { + if (pna->timestamp < timestamp) { + status_trace("Deferring node_announcement for node %s", type_to_string(tmpctx, struct pubkey, &node_id)); + pna->timestamp = timestamp; + tal_free(pna->node_announcement); + pna->node_announcement = tal_dup_arr(pna, u8, node_ann, tal_len(node_ann), 0); + } + tal_free(tmpctx); + return; + } + if (!node) { SUPERVERBOSE("Node not found, was the node_announcement for " "node %s preceded by at least " diff --git a/gossipd/routing.h b/gossipd/routing.h index 2b032c655..b5fd0f22f 100644 --- a/gossipd/routing.h +++ b/gossipd/routing.h @@ -84,6 +84,8 @@ size_t node_map_hash_key(const secp256k1_pubkey *key); bool node_map_node_eq(const struct node *n, const secp256k1_pubkey *key); HTABLE_DEFINE_TYPE(struct node, node_map_keyof_node, node_map_hash_key, node_map_node_eq, node_map); +struct pending_node_map; + enum txout_state { TXOUT_FETCHING, TXOUT_PRESENT, @@ -108,6 +110,8 @@ struct routing_state { /* All known nodes. */ struct node_map *nodes; + struct pending_node_map *pending_node_map; + /* channel_announcement which are pending short_channel_id lookup */ struct list_head pending_cannouncement;