Skip to content

Commit

Permalink
hsmd: add command to allow lightningd to sign channel announcement.
Browse files Browse the repository at this point in the history
Before this it was channeld doing it, which was tied to a particular
channel.  Create an API for lightningd to sign for any channel.

Signed-off-by: Rusty Russell <[email protected]>
  • Loading branch information
rustyrussell committed Jan 31, 2024
1 parent 3e1d34f commit ad4a8a5
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 19 deletions.
3 changes: 2 additions & 1 deletion common/hsm_version.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
* v4 with buried outpoint check: f44fae666895cab0347b3de7c245267c71cc7de834827b83e286e86318c08aec
* v4 with forget_channel: d87c6934ea188f92785d38d7cd0b13ed7f76aa7417f3200baf0c7b5aa832fe29
* v5 with hsmd_revoke_commitment_tx: 5742538f87ef5d5bf55b66dc19e52c8683cfeb1b887d3e64ba530ba9a4d8e638
*/
* v5 with sign_any_cannouncement: 5fdb9068c43a21887dc03f7dce410d2e3eeff6277f0d49b4fc56595a798fd4a4
*/
#define HSM_MIN_VERSION 3
#define HSM_MAX_VERSION 5
#endif /* LIGHTNING_COMMON_HSM_VERSION_H */
2 changes: 2 additions & 0 deletions hsmd/hsmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -671,6 +671,7 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c)
case WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY:
case WIRE_HSMD_DERIVE_SECRET:
case WIRE_HSMD_CANNOUNCEMENT_SIG_REQ:
case WIRE_HSMD_SIGN_ANY_CANNOUNCEMENT_REQ:
case WIRE_HSMD_NODE_ANNOUNCEMENT_SIG_REQ:
case WIRE_HSMD_CUPDATE_SIG_REQ:
case WIRE_HSMD_SIGN_LOCAL_HTLC_TX:
Expand Down Expand Up @@ -722,6 +723,7 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c)
case WIRE_HSMD_CHECK_PUBKEY_REPLY:
case WIRE_HSMD_SIGN_ANCHORSPEND_REPLY:
case WIRE_HSMD_SIGN_HTLC_TX_MINGLE_REPLY:
case WIRE_HSMD_SIGN_ANY_CANNOUNCEMENT_REPLY:
return bad_req_fmt(conn, c, c->msg_in,
"Received an incoming message of type %s, "
"which is not a request",
Expand Down
10 changes: 10 additions & 0 deletions hsmd/hsmd_wire.csv
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,16 @@ msgtype,hsmd_cannouncement_sig_reply,102
msgdata,hsmd_cannouncement_sig_reply,node_signature,secp256k1_ecdsa_signature,
msgdata,hsmd_cannouncement_sig_reply,bitcoin_signature,secp256k1_ecdsa_signature,

msgtype,hsmd_sign_any_cannouncement_req,4
msgdata,hsmd_sign_any_cannouncement_req,calen,u16,
msgdata,hsmd_sign_any_cannouncement_req,ca,u8,calen
msgdata,hsmd_sign_any_cannouncement_req,peerid,node_id,
msgdata,hsmd_sign_any_cannouncement_req,channel_dbid,u64,

msgtype,hsmd_sign_any_cannouncement_reply,104
msgdata,hsmd_sign_any_cannouncement_reply,node_signature,secp256k1_ecdsa_signature,
msgdata,hsmd_sign_any_cannouncement_reply,bitcoin_signature,secp256k1_ecdsa_signature,

msgtype,hsmd_cupdate_sig_req,3
msgdata,hsmd_cupdate_sig_req,culen,u16,
msgdata,hsmd_cupdate_sig_req,cu,u8,culen
Expand Down
72 changes: 54 additions & 18 deletions hsmd/libhsmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ bool hsmd_check_client_capabilities(struct hsmd_client *client,
case WIRE_HSMD_SIGN_ANY_LOCAL_HTLC_TX:
case WIRE_HSMD_SIGN_ANCHORSPEND:
case WIRE_HSMD_SIGN_HTLC_TX_MINGLE:
case WIRE_HSMD_SIGN_ANY_CANNOUNCEMENT_REQ:
return (client->capabilities & HSM_PERM_MASTER) != 0;

/*~ These are messages sent by the HSM so we should never receive them. */
Expand Down Expand Up @@ -178,6 +179,7 @@ bool hsmd_check_client_capabilities(struct hsmd_client *client,
case WIRE_HSMD_CHECK_PUBKEY_REPLY:
case WIRE_HSMD_SIGN_ANCHORSPEND_REPLY:
case WIRE_HSMD_SIGN_HTLC_TX_MINGLE_REPLY:
case WIRE_HSMD_SIGN_ANY_CANNOUNCEMENT_REPLY:
break;
}
return false;
Expand Down Expand Up @@ -972,7 +974,12 @@ static u8 *handle_get_output_scriptpubkey(struct hsmd_client *c,
* defined in BOLT #7, and requires *two* signatures: one from this node's key
* (to prove it's from us), and one from the bitcoin key used to create the
* funding transaction (to prove we own the output). */
static u8 *handle_cannouncement_sig(struct hsmd_client *c, const u8 *msg_in)
static const char *handle_sign_cannouncement(const tal_t *ctx,
const struct node_id *peer_id,
u64 dbid,
const u8 *ca,
secp256k1_ecdsa_signature *node_sig,
secp256k1_ecdsa_signature *bitcoin_sig)
{
/*~ Our autogeneration code doesn't define field offsets, so we just
* copy this from the spec itself.
Expand All @@ -992,10 +999,7 @@ static u8 *handle_cannouncement_sig(struct hsmd_client *c, const u8 *msg_in)
/* First type bytes are the msg type */
size_t offset = 2 + 256;
struct privkey node_pkey;
secp256k1_ecdsa_signature node_sig, bitcoin_sig;
struct sha256_double hash;
u8 *reply;
u8 *ca;
struct pubkey funding_pubkey;
struct privkey funding_privkey;
struct secret channel_seed;
Expand All @@ -1009,32 +1013,61 @@ static u8 *handle_cannouncement_sig(struct hsmd_client *c, const u8 *msg_in)
* mind if you fix this for him! */

/* FIXME: We should cache these. */
get_channel_seed(&c->id, c->dbid, &channel_seed);
get_channel_seed(peer_id, dbid, &channel_seed);
derive_funding_key(&channel_seed, &funding_pubkey, &funding_privkey);

if (tal_count(ca) < offset)
return tal_fmt(ctx, "bad cannounce length %zu", tal_count(ca));

if (fromwire_peektype(ca) != WIRE_CHANNEL_ANNOUNCEMENT)
return tal_fmt(ctx, "Invalid channel announcement");

node_key(&node_pkey, NULL);
sha256_double(&hash, ca + offset, tal_count(ca) - offset);

sign_hash(&node_pkey, &hash, node_sig);
sign_hash(&funding_privkey, &hash, bitcoin_sig);
return NULL;
}

static u8 *handle_cannouncement_sig(struct hsmd_client *c, const u8 *msg_in)
{
u8 *ca;
secp256k1_ecdsa_signature node_sig, bitcoin_sig;
const char *err;

/*~ fromwire_ routines which need to do allocation take a tal context
* as their first field; tmpctx is good here since we won't need it
* after this function. */
if (!fromwire_hsmd_cannouncement_sig_req(tmpctx, msg_in, &ca))
return hsmd_status_malformed_request(c, msg_in);

if (tal_count(ca) < offset)
return hsmd_status_bad_request_fmt(
c, msg_in, "bad cannounce length %zu", tal_count(ca));
err = handle_sign_cannouncement(tmpctx, &c->id, c->dbid, ca,
&node_sig, &bitcoin_sig);
if (err)
return hsmd_status_bad_request_fmt(c, msg_in, "%s", err);

if (fromwire_peektype(ca) != WIRE_CHANNEL_ANNOUNCEMENT)
return hsmd_status_bad_request_fmt(
c, msg_in, "Invalid channel announcement");
return towire_hsmd_cannouncement_sig_reply(NULL, &node_sig, &bitcoin_sig);
}

node_key(&node_pkey, NULL);
sha256_double(&hash, ca + offset, tal_count(ca) - offset);
/* This variant is used by modern lightningd to sign for a particular channel */
static u8 *handle_any_cannouncement_sig(struct hsmd_client *c, const u8 *msg_in)
{
u8 *ca;
struct node_id peer_id;
u64 dbid;
secp256k1_ecdsa_signature node_sig, bitcoin_sig;
const char *err;

if (!fromwire_hsmd_sign_any_cannouncement_req(tmpctx, msg_in, &ca, &peer_id, &dbid))
return hsmd_status_malformed_request(c, msg_in);

sign_hash(&node_pkey, &hash, &node_sig);
sign_hash(&funding_privkey, &hash, &bitcoin_sig);
err = handle_sign_cannouncement(tmpctx, &peer_id, dbid, ca,
&node_sig, &bitcoin_sig);
if (err)
return hsmd_status_bad_request_fmt(c, msg_in, "%s", err);

reply = towire_hsmd_cannouncement_sig_reply(NULL, &node_sig,
&bitcoin_sig);
return reply;
return towire_hsmd_sign_any_cannouncement_reply(NULL, &node_sig, &bitcoin_sig);
}

/*~ It's optional for nodes to send node_announcement, but it lets us set our
Expand Down Expand Up @@ -2026,6 +2059,8 @@ u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client,
return handle_get_channel_basepoints(client, msg);
case WIRE_HSMD_CANNOUNCEMENT_SIG_REQ:
return handle_cannouncement_sig(client, msg);
case WIRE_HSMD_SIGN_ANY_CANNOUNCEMENT_REQ:
return handle_any_cannouncement_sig(client, msg);
case WIRE_HSMD_NODE_ANNOUNCEMENT_SIG_REQ:
return handle_sign_node_announcement(client, msg);
case WIRE_HSMD_CUPDATE_SIG_REQ:
Expand Down Expand Up @@ -2110,6 +2145,7 @@ u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client,
case WIRE_HSMD_CHECK_PUBKEY_REPLY:
case WIRE_HSMD_SIGN_ANCHORSPEND_REPLY:
case WIRE_HSMD_SIGN_HTLC_TX_MINGLE_REPLY:
case WIRE_HSMD_SIGN_ANY_CANNOUNCEMENT_REPLY:
break;
}
return hsmd_status_bad_request(client, msg, "Unknown request");
Expand Down

0 comments on commit ad4a8a5

Please sign in to comment.