diff --git a/gossipd/gossip_generation.c b/gossipd/gossip_generation.c index 6ecf822f3..9fabbe1db 100644 --- a/gossipd/gossip_generation.c +++ b/gossipd/gossip_generation.c @@ -202,7 +202,8 @@ static void update_own_node_announcement(struct daemon *daemon) /* This injects it into the routing code in routing.c; it should not * reject it! */ - err = handle_node_announcement(daemon->rstate, take(nannounce), NULL); + err = handle_node_announcement(daemon->rstate, take(nannounce), + NULL, NULL); if (err) status_failed(STATUS_FAIL_INTERNAL_ERROR, "rejected own node announcement: %s", diff --git a/gossipd/gossip_store.c b/gossipd/gossip_store.c index 30c796069..5b8726881 100644 --- a/gossipd/gossip_store.c +++ b/gossipd/gossip_store.c @@ -721,7 +721,7 @@ u32 gossip_store_load(struct routing_state *rstate, struct gossip_store *gs) case WIRE_NODE_ANNOUNCEMENT: if (!routing_add_node_announcement(rstate, take(msg), gs->len, - NULL)) { + NULL, NULL)) { bad = "Bad node_announcement"; goto badmsg; } diff --git a/gossipd/gossipd.c b/gossipd/gossipd.c index db3079498..284164b4e 100644 --- a/gossipd/gossipd.c +++ b/gossipd/gossipd.c @@ -395,6 +395,18 @@ out: return true; } +static u8 *handle_node_announce(struct peer *peer, const u8 *msg) +{ + bool was_unknown = false; + u8 *err; + + err = handle_node_announcement(peer->daemon->rstate, msg, peer, + &was_unknown); + if (was_unknown) + query_unknown_node(peer->daemon->seeker, peer); + return err; +} + /*~ This is where the per-peer daemons send us messages. It's either forwarded * gossip, or a request for information. We deliberately use non-overlapping * message types so we can distinguish them. */ @@ -414,7 +426,7 @@ static struct io_plan *peer_msg_in(struct io_conn *conn, err = handle_channel_update_msg(peer, msg); goto handled_relay; case WIRE_NODE_ANNOUNCEMENT: - err = handle_node_announcement(peer->daemon->rstate, msg, peer); + err = handle_node_announce(peer, msg); goto handled_relay; case WIRE_QUERY_CHANNEL_RANGE: err = handle_query_channel_range(peer, msg); diff --git a/gossipd/routing.c b/gossipd/routing.c index 65774e4e1..bc1121540 100644 --- a/gossipd/routing.c +++ b/gossipd/routing.c @@ -1517,7 +1517,7 @@ static void process_pending_node_announcement(struct routing_state *rstate, if (!routing_add_node_announcement(rstate, pna->node_announcement, pna->index, - pna->peer_softref)) + pna->peer_softref, NULL)) status_unusual("pending node_announcement %s too old?", tal_hex(tmpctx, pna->node_announcement)); /* Never send this again. */ @@ -2390,7 +2390,8 @@ struct wireaddr *read_addresses(const tal_t *ctx, const u8 *ser) bool routing_add_node_announcement(struct routing_state *rstate, const u8 *msg TAKES, u32 index, - struct peer *peer) + struct peer *peer, + bool *was_unknown) { struct node *node; secp256k1_ecdsa_signature signature; @@ -2400,6 +2401,9 @@ bool routing_add_node_announcement(struct routing_state *rstate, u8 alias[32]; u8 *features, *addresses; + if (was_unknown) + *was_unknown = false; + /* Make sure we own msg, even if we don't save it. */ if (taken(msg)) tal_steal(tmpctx, msg); @@ -2442,6 +2446,8 @@ bool routing_add_node_announcement(struct routing_state *rstate, pna = pending_node_map_get(rstate->pending_node_map, &node_id); if (!pna) { + if (was_unknown) + *was_unknown = true; bad_gossip_order(msg, peer, type_to_string(tmpctx, struct node_id, &node_id)); @@ -2525,7 +2531,7 @@ bool routing_add_node_announcement(struct routing_state *rstate, } u8 *handle_node_announcement(struct routing_state *rstate, const u8 *node_ann, - struct peer *peer) + struct peer *peer, bool *was_unknown) { u8 *serialized; struct sha256_double hash; @@ -2538,6 +2544,9 @@ u8 *handle_node_announcement(struct routing_state *rstate, const u8 *node_ann, struct wireaddr *wireaddrs; size_t len = tal_count(node_ann); + if (was_unknown) + *was_unknown = false; + serialized = tal_dup_arr(tmpctx, u8, node_ann, len, 0); if (!fromwire_node_announcement(tmpctx, serialized, &signature, &features, ×tamp, @@ -2613,7 +2622,7 @@ u8 *handle_node_announcement(struct routing_state *rstate, const u8 *node_ann, } /* May still fail, if we don't know the node. */ - routing_add_node_announcement(rstate, serialized, 0, peer); + routing_add_node_announcement(rstate, serialized, 0, peer, was_unknown); return NULL; } diff --git a/gossipd/routing.h b/gossipd/routing.h index 44ac63761..0880108d2 100644 --- a/gossipd/routing.h +++ b/gossipd/routing.h @@ -392,9 +392,11 @@ u8 *handle_channel_update(struct routing_state *rstate, const u8 *update TAKES, struct peer *peer, struct short_channel_id *unknown_scid); -/* Returns NULL if all OK, otherwise an error for the peer which sent. */ +/* Returns NULL if all OK, otherwise an error for the peer which sent. + * If was_unknown is not NULL, sets it to true if that was the reason for + * the error: the node was unknown to us. */ u8 *handle_node_announcement(struct routing_state *rstate, const u8 *node, - struct peer *peer); + struct peer *peer, bool *was_unknown); /* Get a node: use this instead of node_map_get() */ struct node *get_node(struct routing_state *rstate, @@ -460,7 +462,8 @@ bool routing_add_channel_update(struct routing_state *rstate, bool routing_add_node_announcement(struct routing_state *rstate, const u8 *msg TAKES, u32 index, - struct peer *peer); + struct peer *peer, + bool *was_unknown); /** diff --git a/gossipd/seeker.c b/gossipd/seeker.c index ec36bc129..9f321362b 100644 --- a/gossipd/seeker.c +++ b/gossipd/seeker.c @@ -96,6 +96,10 @@ struct seeker { u8 *nannounce_query_flags; size_t nannounce_offset; + /* Are there any node_ids we didn't know? Implies we're + * missing channels. */ + bool unknown_nodes; + /* Peers we've asked to stream us gossip */ struct peer *gossiper_softref[3]; @@ -148,6 +152,7 @@ struct seeker *new_seeker(struct daemon *daemon) for (size_t i = 0; i < ARRAY_SIZE(seeker->gossiper_softref); i++) seeker->gossiper_softref[i] = NULL; seeker->preferred_peer_softref = NULL; + seeker->unknown_nodes = false; set_state(seeker, STARTING_UP); begin_check_timer(seeker); memleak_add_helper(seeker, memleak_help_seeker); @@ -186,7 +191,12 @@ static struct peer *random_seeker(struct seeker *seeker, { struct peer *peer = seeker->preferred_peer_softref; - if (peer && check_peer(peer)) { + /* 80% chance of immediately choosing a peer who reported the missing + * stuff: they presumably can tell us more about it. We don't + * *always* choose it because it could be simply spamming us with + * invalid announcements to get chosen, and we don't handle that case + * well yet. */ + if (peer && check_peer(peer) && pseudorand(5) != 0) { clear_softref(seeker, &seeker->random_peer_softref); return peer; } @@ -409,6 +419,7 @@ static bool seek_any_stale_scids(struct seeker *seeker) return true; } +/* We can't ask for channels by node_id, so probe at random */ /* Returns true and sets first_blocknum and number_of_blocks if * there's more to find. */ static bool next_block_range(struct seeker *seeker, @@ -846,6 +857,16 @@ set_gossiper: enable_gossip_stream(seeker, peer); } +static bool seek_any_unknown_nodes(struct seeker *seeker) +{ + if (!seeker->unknown_nodes) + return false; + + seeker->unknown_nodes = false; + probe_many_random_scids(seeker); + return true; +} + /* Periodic timer to see how our gossip is going. */ static void seeker_check(struct seeker *seeker) { @@ -867,8 +888,9 @@ static void seeker_check(struct seeker *seeker) break; case NORMAL: maybe_rotate_gossipers(seeker); - if (!seek_any_unknown_scids(seeker)) - seek_any_stale_scids(seeker); + if (!seek_any_unknown_scids(seeker) + && !seek_any_stale_scids(seeker)) + seek_any_unknown_nodes(seeker); break; } @@ -953,3 +975,10 @@ void query_unknown_channel(struct daemon *daemon, if (!add_unknown_scid(daemon->seeker, id, peer)) return; } + +/* This peer told us about an unknown node. Start probing it. */ +void query_unknown_node(struct seeker *seeker, struct peer *peer) +{ + seeker->unknown_nodes = true; + set_preferred_peer(seeker, peer); +} diff --git a/gossipd/seeker.h b/gossipd/seeker.h index cc78bc6cb..af2a752c5 100644 --- a/gossipd/seeker.h +++ b/gossipd/seeker.h @@ -12,6 +12,8 @@ void query_unknown_channel(struct daemon *daemon, struct peer *peer, const struct short_channel_id *id); +void query_unknown_node(struct seeker *seeker, struct peer *peer); + void seeker_setup_peer_gossip(struct seeker *seeker, struct peer *peer); bool remove_unknown_scid(struct seeker *seeker, diff --git a/gossipd/test/run-crc32_of_update.c b/gossipd/test/run-crc32_of_update.c index 1bd0ad13c..480534a56 100644 --- a/gossipd/test/run-crc32_of_update.c +++ b/gossipd/test/run-crc32_of_update.c @@ -58,7 +58,7 @@ u8 *handle_channel_update(struct routing_state *rstate UNNEEDED, const u8 *updat { fprintf(stderr, "handle_channel_update called!\n"); abort(); } /* Generated stub for handle_node_announcement */ u8 *handle_node_announcement(struct routing_state *rstate UNNEEDED, const u8 *node UNNEEDED, - struct peer *peer UNNEEDED) + struct peer *peer UNNEEDED, bool *was_unknown UNNEEDED) { fprintf(stderr, "handle_node_announcement called!\n"); abort(); } /* Generated stub for master_badmsg */ void master_badmsg(u32 type_expected UNNEEDED, const u8 *msg)