seeker: start doing a channel probe if we see unknown node_announcement msgs.

It usually means we're missing something, but there's no way to ask what.
Simply start a broad scid probe.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2019-10-08 12:02:24 +10:30 committed by neil saitug
parent f7cffbad98
commit a1644c1b6e
8 changed files with 70 additions and 14 deletions

View File

@ -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",

View File

@ -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;
}

View File

@ -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);

View File

@ -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, &timestamp,
@ -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;
}

View File

@ -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);
/**

View File

@ -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);
}

View File

@ -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,

View File

@ -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)