gossip: Implement the basic node_announcement

Rather a big commit, but I couldn't figure out how to split it
nicely. It introduces a new message from the channel to the master
signaling that the channel has been announced, so that the master can
take care of announcing the node itself. A provisorial announcement is
created and passed to the HSM, which signs it and passes it back to
the master. Finally the master injects it into gossipd which will take
care of broadcasting it.
This commit is contained in:
Christian Decker
2017-05-07 01:59:48 +02:00
committed by Rusty Russell
parent b99c5620ef
commit daf8866eb5
10 changed files with 139 additions and 0 deletions

View File

@@ -78,6 +78,7 @@ struct node *new_node(struct routing_state *rstate,
n->alias = NULL;
n->hostname = NULL;
n->node_announcement = NULL;
n->last_timestamp = 0;
node_map_add(rstate->nodes, n);
tal_add_destructor(n, destroy_node);

View File

@@ -305,6 +305,9 @@ static void handle_peer_announcement_signatures(struct peer *peer, const u8 *msg
if (peer->funding_locked[LOCAL] && peer->have_sigs[LOCAL]) {
send_channel_announcement(peer);
send_channel_update(peer, false);
/* Tell the master that we just announced the channel,
* so it may announce the node */
daemon_conn_send(&peer->master, take(towire_channel_announced(msg)));
}
}
@@ -1105,6 +1108,9 @@ static void handle_funding_announce_depth(struct peer *peer, const u8 *msg)
if (peer->have_sigs[REMOTE]) {
send_channel_announcement(peer);
send_channel_update(peer, false);
/* Tell the master that we just announced the channel,
* so it may announce the node */
daemon_conn_send(&peer->master, take(towire_channel_announced(msg)));
}
}
@@ -1326,6 +1332,7 @@ static struct io_plan *req_in(struct io_conn *conn, struct daemon_conn *master)
case WIRE_CHANNEL_MALFORMED_HTLC:
case WIRE_CHANNEL_PING_REPLY:
case WIRE_CHANNEL_PEER_BAD_MESSAGE:
case WIRE_CHANNEL_ANNOUNCED:
break;
}
status_failed(WIRE_CHANNEL_BAD_COMMAND, "%u %s", t,

View File

@@ -117,3 +117,5 @@ channel_ping,0,len,u16
channel_ping_reply,111
channel_ping_reply,0,totlen,u16
# Channeld tells the master that the channel has been announced
channel_announced,12
1 # Shouldn't happen
117
118
119
120
121

View File

@@ -660,6 +660,15 @@ static struct io_plan *resolve_channel_req(struct io_conn *conn,
return daemon_conn_read_next(conn, &daemon->master);
}
static void handle_forwarded_msg(struct io_conn *conn, struct daemon *daemon, const u8 *msg)
{
u8 *payload;
if (!fromwire_gossip_forwarded_msg(msg, msg, NULL, &payload)) {
status_trace("Malformed forwarded message: %s", tal_hex(trc, msg));
return;
}
handle_gossip_msg(daemon->rstate, payload);
}
static struct io_plan *recv_req(struct io_conn *conn, struct daemon_conn *master)
{
struct daemon *daemon = container_of(master, struct daemon, master);
@@ -692,6 +701,9 @@ static struct io_plan *recv_req(struct io_conn *conn, struct daemon_conn *master
case WIRE_GOSSIP_RESOLVE_CHANNEL_REQUEST:
return resolve_channel_req(conn, daemon, daemon->master.msg_in);
case WIRE_GOSSIP_FORWARDED_MSG:
handle_forwarded_msg(conn, daemon, daemon->master.msg_in);
return daemon_conn_read_next(conn, &daemon->master);
case WIRE_GOSSIPCTL_RELEASE_PEER_REPLY:
case WIRE_GOSSIP_GETNODES_REPLY:
case WIRE_GOSSIP_GETROUTE_REPLY:

View File

@@ -98,3 +98,9 @@ gossip_resolve_channel_request,0,channel_id,struct short_channel_id
gossip_resolve_channel_reply,109
gossip_resolve_channel_reply,0,num_keys,u16
gossip_resolve_channel_reply,0,keys,num_keys*struct pubkey
# The main daemon forward some gossip message to gossipd, allows injecting
# arbitrary gossip messages.
gossip_forwarded_msg,10
gossip_forwarded_msg,0,msglen,2
gossip_forwarded_msg,2,msg,msglen
1 # These are fatal.
98
99
100
101
102
103
104
105
106

View File

@@ -148,6 +148,7 @@ static int gossip_msg(struct subd *gossip, const u8 *msg, const int *fds)
case WIRE_GOSSIP_GETCHANNELS_REQUEST:
case WIRE_GOSSIP_PING:
case WIRE_GOSSIP_RESOLVE_CHANNEL_REQUEST:
case WIRE_GOSSIP_FORWARDED_MSG:
/* This is a reply, so never gets through to here. */
case WIRE_GOSSIPCTL_RELEASE_PEER_REPLY:
case WIRE_GOSSIP_GETNODES_REPLY:

View File

@@ -511,6 +511,37 @@ static void sign_funding_tx(struct daemon_conn *master, const u8 *msg)
tal_free(tmpctx);
}
static void sign_node_announcement(struct daemon_conn *master, const u8 *msg)
{
/* 2 bytes msg type + 64 bytes signature */
size_t offset = 66;
struct sha256_double hash;
struct privkey node_pkey;
secp256k1_ecdsa_signature sig;
u8 *reply;
u8 *ann;
if (!fromwire_hsmctl_node_announcement_sig_req(msg, msg, NULL, &ann)) {
status_trace("Failed to parse node_announcement_sig_req: %s",
tal_hex(trc, msg));
return;
}
if (tal_len(ann) < offset) {
status_trace("Node announcement too short: %s", tal_hex(trc, msg));
return;
}
/* FIXME(cdecker) Check the node announcement's content */
node_key(&node_pkey, NULL);
sha256_double(&hash, ann + offset, tal_len(ann) - offset);
sign_hash(&node_pkey, &hash, &sig);
reply = towire_hsmctl_node_announcement_sig_reply(msg, &sig);
daemon_conn_send(master, take(reply));
}
static struct io_plan *control_received_req(struct io_conn *conn,
struct daemon_conn *master)
{
@@ -533,6 +564,10 @@ static struct io_plan *control_received_req(struct io_conn *conn,
sign_funding_tx(master, master->msg_in);
return daemon_conn_read_next(conn, master);
case WIRE_HSMCTL_NODE_ANNOUNCEMENT_SIG_REQ:
sign_node_announcement(master, master->msg_in);
return daemon_conn_read_next(conn, master);
case WIRE_HSMCTL_INIT_REPLY:
case WIRE_HSMCTL_HSMFD_ECDH_FD_REPLY:
case WIRE_HSMCTL_HSMFD_CHANNELD_REPLY:
@@ -543,6 +578,7 @@ static struct io_plan *control_received_req(struct io_conn *conn,
case WIRE_HSMSTATUS_FD_FAILED:
case WIRE_HSMSTATUS_KEY_FAILED:
case WIRE_HSMSTATUS_CLIENT_BAD_REQUEST:
case WIRE_HSMCTL_NODE_ANNOUNCEMENT_SIG_REPLY:
break;
}

View File

@@ -50,3 +50,11 @@ hsmctl_hsmfd_channeld,0,unique_id,8
# Empty reply, just an fd
hsmctl_hsmfd_channeld_reply,105
# Master asks the HSM to sign a node_announcement
hsmctl_node_announcement_sig_req,6
hsmctl_node_announcement_sig_req,0,annlen,2
hsmctl_node_announcement_sig_req,2,announcement,annlen*u8
hsmctl_node_announcement_sig_reply,106
hsmctl_node_announcement_sig_reply,0,signature,secp256k1_ecdsa_signature
1 # These are fatal.
50
51
52
53
54
55
56
57
58
59
60

View File

@@ -73,12 +73,14 @@ static int hsm_msg(struct subd *hsm, const u8 *msg, const int *fds)
case WIRE_HSMCTL_HSMFD_ECDH:
case WIRE_HSMCTL_HSMFD_CHANNELD:
case WIRE_HSMCTL_SIGN_FUNDING:
case WIRE_HSMCTL_NODE_ANNOUNCEMENT_SIG_REQ:
/* Replies should be paired to individual requests. */
case WIRE_HSMCTL_INIT_REPLY:
case WIRE_HSMCTL_HSMFD_CHANNELD_REPLY:
case WIRE_HSMCTL_HSMFD_ECDH_FD_REPLY:
case WIRE_HSMCTL_SIGN_FUNDING_REPLY:
case WIRE_HSMCTL_NODE_ANNOUNCEMENT_SIG_REPLY:
errx(1, "HSM gave invalid message %s", hsm_wire_type_name(t));
}
return 0;

View File

@@ -1249,6 +1249,67 @@ static int peer_failed_malformed_htlc(struct peer *peer, const u8 *msg)
return 0;
}
/* Create a node_announcement with the given signature. It may be NULL
* in the case we need to create a provisional announcement for the
* HSM to sign. */
static u8 *create_node_announcement(const tal_t *ctx, struct lightningd *ld,
secp256k1_ecdsa_signature *sig)
{
u32 timestamp = time_now().ts.tv_sec;
u8 rgb[3] = {0x77, 0x88, 0x99};
u8 alias[32];
u8 *features = NULL;
u8 *addresses = NULL;
u8 *announcement;
if (!sig) {
sig = tal(ctx, secp256k1_ecdsa_signature);
memset(sig, 0, sizeof(*sig));
}
memset(alias, 0, sizeof(alias));
announcement =
towire_node_announcement(ctx, sig, timestamp, &ld->dstate.id, rgb,
alias, features, addresses);
return announcement;
}
/* We got the signature for out provisional node_announcement back
* from the HSM, create the real announcement and forward it to
* gossipd so it can take care of forwarding it. */
static bool send_node_announcement_got_sig(struct subd *hsm, const u8 *msg,
const int *fds,
struct lightningd *ld)
{
tal_t *tmpctx = tal_tmpctx(hsm);
secp256k1_ecdsa_signature sig;
u8 *announcement, *wrappedmsg;
if (!fromwire_hsmctl_node_announcement_sig_reply(msg, NULL, &sig)) {
log_debug(ld->log,
"HSM returned an invalid node_announcement sig");
return false;
}
announcement = create_node_announcement(tmpctx, ld, &sig);
wrappedmsg = towire_gossip_forwarded_msg(tmpctx, announcement);
subd_send_msg(ld->gossip, take(wrappedmsg));
tal_free(tmpctx);
return true;
}
/* We were informed by channeld that it announced the channel and sent
* an update, so we can now start sending a node_announcement. The
* first step is to build the provisional announcement and ask the HSM
* to sign it. */
static void peer_channel_announced(struct peer *peer, const u8 *msg)
{
struct lightningd *ld = peer->ld;
tal_t *tmpctx = tal_tmpctx(ld);
u8 *req;
req = towire_hsmctl_node_announcement_sig_req(
tmpctx, create_node_announcement(tmpctx, ld, NULL));
subd_req(ld, ld->hsm, take(req), -1, 0,
send_node_announcement_got_sig, ld);
tal_free(tmpctx);
}
static int channel_msg(struct subd *sd, const u8 *msg, const int *unused)
{
enum channel_wire_type t = fromwire_peektype(msg);
@@ -1268,6 +1329,9 @@ static int channel_msg(struct subd *sd, const u8 *msg, const int *unused)
return peer_failed_htlc(sd->peer, msg);
case WIRE_CHANNEL_MALFORMED_HTLC:
return peer_failed_malformed_htlc(sd->peer, msg);
case WIRE_CHANNEL_ANNOUNCED:
peer_channel_announced(sd->peer, msg);
break;
/* We never see fatal ones. */
case WIRE_CHANNEL_BAD_COMMAND: