Browse Source

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 <decker.christian@gmail.com>
ppa-0.6.1
Christian Decker 7 years ago
committed by Rusty Russell
parent
commit
0790d9b52f
  1. 72
      gossipd/routing.c
  2. 4
      gossipd/routing.h

72
gossipd/routing.c

@ -53,6 +53,28 @@ struct pending_cannouncement {
u32 update_timestamps[2]; 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 * routing_channel keeps track of the indices in the broadcast queue
* for the corresponding messages. This way we always know exactly * 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); list_head_init(&rstate->pending_cannouncement);
uintmap_init(&rstate->channels); uintmap_init(&rstate->channels);
rstate->pending_node_map = tal(ctx, struct pending_node_map);
pending_node_map_init(rstate->pending_node_map);
return rstate; return rstate;
} }
@ -596,6 +621,30 @@ void channel_add_connection(struct routing_state *rstate,
tal_add_destructor2(nc, remove_connection_from_channel, 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( const struct short_channel_id *handle_channel_announcement(
struct routing_state *rstate, struct routing_state *rstate,
const u8 *announce TAKES) const u8 *announce TAKES)
@ -697,6 +746,11 @@ const struct short_channel_id *handle_channel_announcement(
chan->public = true; chan->public = true;
uintmap_add(&rstate->channels, scid, chan); 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); list_add_tail(&rstate->pending_cannouncement, &pending->list);
return &pending->short_channel_id; return &pending->short_channel_id;
} }
@ -791,6 +845,9 @@ bool handle_pending_cannouncement(struct routing_state *rstate,
if (pending->updates[1]) if (pending->updates[1])
handle_channel_update(rstate, 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); tal_free(pending);
return local && forward; return local && forward;
} }
@ -1004,8 +1061,23 @@ void handle_node_announcement(
tal_free(tmpctx); tal_free(tmpctx);
return; return;
} }
node = get_node(rstate, &node_id); 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) { if (!node) {
SUPERVERBOSE("Node not found, was the node_announcement for " SUPERVERBOSE("Node not found, was the node_announcement for "
"node %s preceded by at least " "node %s preceded by at least "

4
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); 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); 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 { enum txout_state {
TXOUT_FETCHING, TXOUT_FETCHING,
TXOUT_PRESENT, TXOUT_PRESENT,
@ -108,6 +110,8 @@ struct routing_state {
/* All known nodes. */ /* All known nodes. */
struct node_map *nodes; struct node_map *nodes;
struct pending_node_map *pending_node_map;
/* channel_announcement which are pending short_channel_id lookup */ /* channel_announcement which are pending short_channel_id lookup */
struct list_head pending_cannouncement; struct list_head pending_cannouncement;

Loading…
Cancel
Save