Browse Source

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.
ppa-0.6.1
Christian Decker 8 years ago
committed by Rusty Russell
parent
commit
daf8866eb5
  1. 1
      daemon/routing.c
  2. 7
      lightningd/channel/channel.c
  3. 2
      lightningd/channel/channel_wire.csv
  4. 12
      lightningd/gossip/gossip.c
  5. 6
      lightningd/gossip/gossip_wire.csv
  6. 1
      lightningd/gossip_control.c
  7. 36
      lightningd/hsm/hsm.c
  8. 8
      lightningd/hsm/hsm_wire.csv
  9. 2
      lightningd/hsm_control.c
  10. 64
      lightningd/peer_control.c

1
daemon/routing.c

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

7
lightningd/channel/channel.c

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

2
lightningd/channel/channel_wire.csv

@ -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
Can't render this file because it has a wrong number of fields in line 2.

12
lightningd/gossip/gossip.c

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

6
lightningd/gossip/gossip_wire.csv

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

Can't render this file because it has a wrong number of fields in line 2.

1
lightningd/gossip_control.c

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

36
lightningd/hsm/hsm.c

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

8
lightningd/hsm/hsm_wire.csv

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

Can't render this file because it has a wrong number of fields in line 2.

2
lightningd/hsm_control.c

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

64
lightningd/peer_control.c

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

Loading…
Cancel
Save