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:
parent
7ee5da858c
commit
4d8b29089b
143
gossipd/gossip.c
143
gossipd/gossip.c
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
|
@ -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:
|
||||||
|
|
Loading…
Reference in New Issue