gossipd: wire up infrastructure to generate query_short_channel_ids msg.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2018-06-04 13:52:25 +09:30
parent 7ee5da858c
commit 4d8b29089b
3 changed files with 151 additions and 5 deletions

View File

@ -228,6 +228,9 @@ struct peer {
/* Is it time to continue the staggered broadcast? */ /* Is it time to continue the staggered broadcast? */
bool gossip_sync; bool gossip_sync;
/* How many query responses are we expecting? */
size_t num_scid_queries_outstanding;
/* Only one of these is set: */ /* Only one of these is set: */
struct local_peer_state *local; struct local_peer_state *local;
struct daemon_conn *remote; struct daemon_conn *remote;
@ -348,6 +351,7 @@ static struct peer *new_peer(const tal_t *ctx,
peer->scid_query_idx = 0; peer->scid_query_idx = 0;
peer->scid_query_nodes = NULL; peer->scid_query_nodes = NULL;
peer->scid_query_nodes_idx = 0; peer->scid_query_nodes_idx = 0;
peer->num_scid_queries_outstanding = 0;
return peer; return peer;
} }
@ -403,6 +407,30 @@ static void reached_peer(struct peer *peer, struct io_conn *conn)
tal_free(r); tal_free(r);
} }
static u8 *encode_short_channel_ids_start(const tal_t *ctx)
{
/* BOLT #7:
*
* Encoding types:
* * `0`: uncompressed array of `short_channel_id` types, in ascending
* order.
*/
u8 *encoded = tal_arr(tmpctx, u8, 0);
towire_u8(&encoded, 0);
return encoded;
}
static void encode_add_short_channel_id(u8 **encoded,
const struct short_channel_id *scid)
{
towire_short_channel_id(encoded, scid);
}
static bool encode_short_channel_ids_end(u8 **encoded, size_t max_bytes)
{
return tal_len(*encoded) <= max_bytes;
}
static void queue_peer_msg(struct peer *peer, const u8 *msg TAKES) static void queue_peer_msg(struct peer *peer, const u8 *msg TAKES)
{ {
if (peer->local) { if (peer->local) {
@ -820,6 +848,34 @@ static void handle_pong(struct peer *peer, const u8 *pong)
tal_len(pong)))); tal_len(pong))));
} }
static void handle_reply_short_channel_ids_end(struct peer *peer, u8 *msg)
{
struct bitcoin_blkid chain;
u8 complete;
if (!fromwire_reply_short_channel_ids_end(msg, &chain, &complete)) {
peer_error(peer, "Bad reply_short_channel_ids_end %s",
tal_hex(tmpctx, msg));
return;
}
if (!structeq(&peer->daemon->rstate->chain_hash, &chain)) {
peer_error(peer, "reply_short_channel_ids_end for bad chain: %s",
tal_hex(tmpctx, msg));
return;
}
if (peer->num_scid_queries_outstanding == 0) {
peer_error(peer, "unexpected reply_short_channel_ids_end: %s",
tal_hex(tmpctx, msg));
return;
}
peer->num_scid_queries_outstanding--;
msg = towire_gossip_scids_reply(msg, true, complete);
daemon_conn_send(&peer->daemon->master, take(msg));
}
/* If master asks us to release peer, we attach this destructor in case it /* If master asks us to release peer, we attach this destructor in case it
* dies while we're waiting for it to finish IO */ * dies while we're waiting for it to finish IO */
static void fail_release(struct peer *peer) static void fail_release(struct peer *peer)
@ -903,6 +959,10 @@ static struct io_plan *peer_msgin(struct io_conn *conn,
handle_query_short_channel_ids(peer, msg); handle_query_short_channel_ids(peer, msg);
return peer_next_in(conn, peer); return peer_next_in(conn, peer);
case WIRE_REPLY_SHORT_CHANNEL_IDS_END:
handle_reply_short_channel_ids_end(peer, msg);
return peer_next_in(conn, peer);
case WIRE_OPEN_CHANNEL: case WIRE_OPEN_CHANNEL:
case WIRE_CHANNEL_REESTABLISH: case WIRE_CHANNEL_REESTABLISH:
case WIRE_ACCEPT_CHANNEL: case WIRE_ACCEPT_CHANNEL:
@ -927,7 +987,6 @@ static struct io_plan *peer_msgin(struct io_conn *conn,
/* This will wait. */ /* This will wait. */
return peer_next_in(conn, peer); return peer_next_in(conn, peer);
case WIRE_REPLY_SHORT_CHANNEL_IDS_END:
case WIRE_QUERY_CHANNEL_RANGE: case WIRE_QUERY_CHANNEL_RANGE:
case WIRE_REPLY_CHANNEL_RANGE: case WIRE_REPLY_CHANNEL_RANGE:
case WIRE_GOSSIP_TIMESTAMP_FILTER: case WIRE_GOSSIP_TIMESTAMP_FILTER:
@ -1037,7 +1096,7 @@ static bool create_next_scid_reply(struct peer *peer)
struct chan *chan; struct chan *chan;
chan = get_channel(rstate, &peer->scid_queries[i]); chan = get_channel(rstate, &peer->scid_queries[i]);
if (!chan || is_chan_public(chan)) if (!chan || !is_chan_public(chan))
continue; continue;
queue_peer_msg(peer, chan->channel_announce); queue_peer_msg(peer, chan->channel_announce);
@ -1336,6 +1395,8 @@ static struct io_plan *owner_msg_in(struct io_conn *conn,
queue_peer_msg(peer, take(err)); queue_peer_msg(peer, take(err));
} else if (type == WIRE_QUERY_SHORT_CHANNEL_IDS) { } else if (type == WIRE_QUERY_SHORT_CHANNEL_IDS) {
handle_query_short_channel_ids(peer, dc->msg_in); handle_query_short_channel_ids(peer, dc->msg_in);
} else if (type == WIRE_REPLY_SHORT_CHANNEL_IDS_END) {
handle_reply_short_channel_ids_end(peer, dc->msg_in);
} else if (type == WIRE_GOSSIP_GET_UPDATE) { } else if (type == WIRE_GOSSIP_GET_UPDATE) {
handle_get_update(peer, dc->msg_in); handle_get_update(peer, dc->msg_in);
} else if (type == WIRE_GOSSIP_LOCAL_ADD_CHANNEL) { } else if (type == WIRE_GOSSIP_LOCAL_ADD_CHANNEL) {
@ -1751,6 +1812,7 @@ static struct io_plan *getnodes(struct io_conn *conn, struct daemon *daemon,
return daemon_conn_read_next(conn, &daemon->master); return daemon_conn_read_next(conn, &daemon->master);
} }
#if DEVELOPER
static struct io_plan *ping_req(struct io_conn *conn, struct daemon *daemon, static struct io_plan *ping_req(struct io_conn *conn, struct daemon *daemon,
const u8 *msg) const u8 *msg)
{ {
@ -1793,6 +1855,67 @@ out:
return daemon_conn_read_next(conn, &daemon->master); return daemon_conn_read_next(conn, &daemon->master);
} }
static struct io_plan *query_scids_req(struct io_conn *conn,
struct daemon *daemon,
const u8 *msg)
{
struct pubkey id;
struct short_channel_id *scids;
struct peer *peer;
u8 *encoded;
/* BOLT #7:
*
* 1. type: 261 (`query_short_channel_ids`) (`gossip_queries`)
* 2. data:
* * [`32`:`chain_hash`]
* * [`2`:`len`]
* * [`len`:`encoded_short_ids`]
*/
const size_t reply_overhead = 32 + 2;
const size_t max_encoded_bytes = 65535 - 2 - reply_overhead;
if (!fromwire_gossip_query_scids(msg, msg, &id, &scids))
master_badmsg(WIRE_GOSSIP_QUERY_SCIDS, msg);
peer = find_peer(daemon, &id);
if (!peer) {
status_broken("query_scids: unknown peer %s",
type_to_string(tmpctx, struct pubkey, &id));
goto fail;
}
if (!feature_offered(peer->lfeatures, LOCAL_GOSSIP_QUERIES)) {
status_broken("query_scids: no gossip_query support in peer %s",
type_to_string(tmpctx, struct pubkey, &id));
goto fail;
}
encoded = encode_short_channel_ids_start(tmpctx);
for (size_t i = 0; i < tal_count(scids); i++)
encode_add_short_channel_id(&encoded, &scids[i]);
if (!encode_short_channel_ids_end(&encoded, max_encoded_bytes)) {
status_broken("query_short_channel_ids: %zu is too many",
tal_count(scids));
goto fail;
}
msg = towire_query_short_channel_ids(NULL, &daemon->rstate->chain_hash,
encoded);
queue_peer_msg(peer, take(msg));
peer->num_scid_queries_outstanding++;
status_trace("sending query for %zu scids", tal_count(scids));
out:
return daemon_conn_read_next(conn, &daemon->master);
fail:
daemon_conn_send(&daemon->master,
take(towire_gossip_scids_reply(NULL, false, false)));
goto out;
}
#endif /* DEVELOPER */
static int make_listen_fd(int domain, void *addr, socklen_t len, bool mayfail) static int make_listen_fd(int domain, void *addr, socklen_t len, bool mayfail)
{ {
int fd = socket(domain, SOCK_STREAM, 0); int fd = socket(domain, SOCK_STREAM, 0);
@ -2966,9 +3089,6 @@ static struct io_plan *recv_req(struct io_conn *conn, struct daemon_conn *master
case WIRE_GOSSIP_GETCHANNELS_REQUEST: case WIRE_GOSSIP_GETCHANNELS_REQUEST:
return getchannels_req(conn, daemon, daemon->master.msg_in); return getchannels_req(conn, daemon, daemon->master.msg_in);
case WIRE_GOSSIP_PING:
return ping_req(conn, daemon, daemon->master.msg_in);
case WIRE_GOSSIP_RESOLVE_CHANNEL_REQUEST: case WIRE_GOSSIP_RESOLVE_CHANNEL_REQUEST:
return resolve_channel_req(conn, daemon, daemon->master.msg_in); return resolve_channel_req(conn, daemon, daemon->master.msg_in);
@ -3008,6 +3128,18 @@ static struct io_plan *recv_req(struct io_conn *conn, struct daemon_conn *master
case WIRE_GOSSIP_LOCAL_CHANNEL_CLOSE: case WIRE_GOSSIP_LOCAL_CHANNEL_CLOSE:
return handle_local_channel_close(conn, daemon, master->msg_in); return handle_local_channel_close(conn, daemon, master->msg_in);
#if DEVELOPER
case WIRE_GOSSIP_PING:
return ping_req(conn, daemon, daemon->master.msg_in);
case WIRE_GOSSIP_QUERY_SCIDS:
return query_scids_req(conn, daemon, daemon->master.msg_in);
#else
case WIRE_GOSSIP_PING:
case WIRE_GOSSIP_QUERY_SCIDS:
break;
#endif /* !DEVELOPER */
/* We send these, we don't receive them */ /* We send these, we don't receive them */
case WIRE_GOSSIPCTL_ACTIVATE_REPLY: case WIRE_GOSSIPCTL_ACTIVATE_REPLY:
case WIRE_GOSSIPCTL_RELEASE_PEER_REPLY: case WIRE_GOSSIPCTL_RELEASE_PEER_REPLY:
@ -3017,6 +3149,7 @@ static struct io_plan *recv_req(struct io_conn *conn, struct daemon_conn *master
case WIRE_GOSSIP_GETCHANNELS_REPLY: case WIRE_GOSSIP_GETCHANNELS_REPLY:
case WIRE_GOSSIP_GETPEERS_REPLY: case WIRE_GOSSIP_GETPEERS_REPLY:
case WIRE_GOSSIP_PING_REPLY: case WIRE_GOSSIP_PING_REPLY:
case WIRE_GOSSIP_SCIDS_REPLY:
case WIRE_GOSSIP_RESOLVE_CHANNEL_REPLY: case WIRE_GOSSIP_RESOLVE_CHANNEL_REPLY:
case WIRE_GOSSIP_PEER_CONNECTED: case WIRE_GOSSIP_PEER_CONNECTED:
case WIRE_GOSSIPCTL_CONNECT_TO_PEER_RESULT: case WIRE_GOSSIPCTL_CONNECT_TO_PEER_RESULT:

View File

@ -155,6 +155,17 @@ gossip_ping_reply,,sent,bool
# 0 == no pong expected # 0 == no pong expected
gossip_ping_reply,,totlen,u16 gossip_ping_reply,,totlen,u16
# Test of query_short_channel_ids. Master->gossipd
gossip_query_scids,3031
gossip_query_scids,,id,struct pubkey
gossip_query_scids,,num_ids,u16
gossip_query_scids,,ids,num_ids*struct short_channel_id
# Gossipd -> master
gossip_scids_reply,3131
gossip_scids_reply,,ok,bool
gossip_scids_reply,,complete,bool
# Given a short_channel_id, return the endpoints # Given a short_channel_id, return the endpoints
gossip_resolve_channel_request,3009 gossip_resolve_channel_request,3009
gossip_resolve_channel_request,,channel_id,struct short_channel_id gossip_resolve_channel_request,,channel_id,struct short_channel_id

1 #include <common/cryptomsg.h>
155 gossip_get_update,,short_channel_id,struct short_channel_id gossip_getpeers_reply,3111
156 # If channel isn't known, update will be empty. gossip_getpeers_reply,,num,u16
157 gossip_get_update_reply,3112 gossip_getpeers_reply,,id,num*struct pubkey
158 gossip_getpeers_reply,,addr,num*struct wireaddr_internal
159 gossip_getpeers_reply,,numnodes,u16
160 gossip_getpeers_reply,,nodes,numnodes*struct gossip_getnodes_entry
161 # Channel daemon can ask for updates for a specific channel, for sending
162 # errors. Must be distinct from WIRE_CHANNEL_ANNOUNCEMENT etc. gossip msgs!
163 gossip_get_update,3012
164 gossip_get_update,,short_channel_id,struct short_channel_id
165 # If channel isn't known, update will be empty.
166 gossip_get_update_reply,3112
167 gossip_get_update_reply,,len,u16
168 gossip_get_update_reply,,update,len*u8
169 gossip_get_update_reply,,len,u16 # Gossipd can tell channeld etc about gossip to fwd.
170 gossip_get_update_reply,,update,len*u8 gossip_send_gossip,3016
171 # Gossipd can tell channeld etc about gossip to fwd. gossip_send_gossip,,len,u16

View File

@ -136,6 +136,7 @@ static unsigned gossip_msg(struct subd *gossip, const u8 *msg, const int *fds)
case WIRE_GOSSIP_OUTPOINT_SPENT: case WIRE_GOSSIP_OUTPOINT_SPENT:
case WIRE_GOSSIP_ROUTING_FAILURE: case WIRE_GOSSIP_ROUTING_FAILURE:
case WIRE_GOSSIP_MARK_CHANNEL_UNROUTABLE: case WIRE_GOSSIP_MARK_CHANNEL_UNROUTABLE:
case WIRE_GOSSIP_QUERY_SCIDS:
case WIRE_GOSSIPCTL_PEER_DISCONNECT: case WIRE_GOSSIPCTL_PEER_DISCONNECT:
case WIRE_GOSSIPCTL_PEER_IMPORTANT: case WIRE_GOSSIPCTL_PEER_IMPORTANT:
case WIRE_GOSSIPCTL_PEER_DISCONNECTED: case WIRE_GOSSIPCTL_PEER_DISCONNECTED:
@ -147,6 +148,7 @@ static unsigned gossip_msg(struct subd *gossip, const u8 *msg, const int *fds)
case WIRE_GOSSIP_GETCHANNELS_REPLY: case WIRE_GOSSIP_GETCHANNELS_REPLY:
case WIRE_GOSSIP_GETPEERS_REPLY: case WIRE_GOSSIP_GETPEERS_REPLY:
case WIRE_GOSSIP_PING_REPLY: case WIRE_GOSSIP_PING_REPLY:
case WIRE_GOSSIP_SCIDS_REPLY:
case WIRE_GOSSIP_RESOLVE_CHANNEL_REPLY: case WIRE_GOSSIP_RESOLVE_CHANNEL_REPLY:
case WIRE_GOSSIPCTL_RELEASE_PEER_REPLY: case WIRE_GOSSIPCTL_RELEASE_PEER_REPLY:
case WIRE_GOSSIPCTL_RELEASE_PEER_REPLYFAIL: case WIRE_GOSSIPCTL_RELEASE_PEER_REPLYFAIL: