gossipd: handle query_short_channel_ids message.

This doesn't handle zlib yet.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2018-06-04 13:51:25 +09:30
parent 32c39c2979
commit 7ee5da858c
1 changed files with 105 additions and 2 deletions

View File

@ -694,6 +694,105 @@ static u8 *handle_gossip_msg(struct daemon *daemon, const u8 *msg,
return NULL;
}
/* BOLT #7:
*
* the first byte indicates the encoding, the rest contains the data.
*
* Encoding types:
* * `0`: uncompressed array of `short_channel_id` types, in ascending order.
*/
static struct short_channel_id *decode_short_ids(const tal_t *ctx,
const u8 *encoded)
{
struct short_channel_id *scids;
size_t max = tal_len(encoded), n;
u8 type;
/* BOLT #7:
*
* The receiver:
* - if the first byte of `encoded_short_ids` is not zero:
* - MAY fail the connection
* - if `encoded_short_ids` does not decode into a whole number of
* `short_channel_id`:
* - MAY fail the connection
*/
type = fromwire_u8(&encoded, &max);
if (type != 0)
return NULL;
n = 0;
scids = tal_arr(ctx, struct short_channel_id, n);
while (max) {
tal_resize(&scids, n+1);
fromwire_short_channel_id(&encoded, &max, &scids[n++]);
}
/* encoded is set to NULL if we ran over */
if (!encoded)
return tal_free(scids);
return scids;
}
static void handle_query_short_channel_ids(struct peer *peer, u8 *msg)
{
struct routing_state *rstate =peer->daemon->rstate;
struct bitcoin_blkid chain;
u8 *encoded;
struct short_channel_id *scids;
if (!fromwire_query_short_channel_ids(tmpctx, msg, &chain, &encoded)) {
peer_error(peer, "Bad query_short_channel_ids %s",
tal_hex(tmpctx, msg));
return;
}
if (!structeq(&rstate->chain_hash, &chain)) {
status_trace("%s sent query_short_channel_ids chainhash %s",
type_to_string(tmpctx, struct pubkey, &peer->id),
type_to_string(tmpctx, struct bitcoin_blkid, &chain));
return;
}
/* BOLT #7:
*
* - if it has not sent `reply_short_channel_ids_end` to a
* previously received `query_short_channel_ids` from this
* sender:
* - MAY fail the connection.
*/
if (peer->scid_queries || peer->scid_query_nodes) {
peer_error(peer, "Bad second query_short_channel_ids");
return;
}
scids = decode_short_ids(tmpctx, encoded);
if (!scids) {
peer_error(peer, "Bad query_short_channel_ids encoding %s",
tal_hex(tmpctx, encoded));
return;
}
/* BOLT #7:
*
* - SHOULD respond to each known `short_channel_id` with a
* `channel_announce` and the latest `channel_update`s for each end
* - SHOULD NOT wait for the next outgoing announcement flush to send
* these.
*/
peer->scid_queries = tal_steal(peer, scids);
peer->scid_query_idx = 0;
peer->scid_query_nodes = tal_arr(peer, struct pubkey, 0);
/* Wake writer. */
if (peer->local)
/* Notify the peer-write loop */
msg_wake(&peer->local->peer_out);
else
/* Notify the daemon_conn-write loop */
msg_wake(&peer->remote->out);
}
static void handle_ping(struct peer *peer, u8 *ping)
{
u8 *pong;
@ -800,6 +899,10 @@ static struct io_plan *peer_msgin(struct io_conn *conn,
handle_pong(peer, msg);
return peer_next_in(conn, peer);
case WIRE_QUERY_SHORT_CHANNEL_IDS:
handle_query_short_channel_ids(peer, msg);
return peer_next_in(conn, peer);
case WIRE_OPEN_CHANNEL:
case WIRE_CHANNEL_REESTABLISH:
case WIRE_ACCEPT_CHANNEL:
@ -824,7 +927,6 @@ static struct io_plan *peer_msgin(struct io_conn *conn,
/* This will wait. */
return peer_next_in(conn, peer);
case WIRE_QUERY_SHORT_CHANNEL_IDS:
case WIRE_REPLY_SHORT_CHANNEL_IDS_END:
case WIRE_QUERY_CHANNEL_RANGE:
case WIRE_REPLY_CHANNEL_RANGE:
@ -1232,7 +1334,8 @@ static struct io_plan *owner_msg_in(struct io_conn *conn,
err = handle_gossip_msg(peer->daemon, dc->msg_in, "subdaemon");
if (err)
queue_peer_msg(peer, take(err));
} else if (type == WIRE_QUERY_SHORT_CHANNEL_IDS) {
handle_query_short_channel_ids(peer, dc->msg_in);
} else if (type == WIRE_GOSSIP_GET_UPDATE) {
handle_get_update(peer, dc->msg_in);
} else if (type == WIRE_GOSSIP_LOCAL_ADD_CHANNEL) {