diff --git a/common/hsm_version.h b/common/hsm_version.h index 5c5c22af0..abe7f887b 100644 --- a/common/hsm_version.h +++ b/common/hsm_version.h @@ -13,6 +13,7 @@ * v4: 41a730986c51b930e2d8d12b3169d24966c2004e08d424bdda310edbbde5ba70 * v4 with check_pubkey: 48b3992745aa3c6ab6ce5cdaee9082cb7d70017f523d322015e9710bf49fd193 * v4 with sign_any_penalty_to_us: ead7963185194a515d1f14d2c44401392575299d68ce9a13d8a12baff3cf4f35 + * v4 with sign_anchorspend: 8a30722e38b56e82af566b9629ff18da01fcebd1e80ec67f04d8b3a2fa66d81c */ #define HSM_MIN_VERSION 3 #define HSM_MAX_VERSION 4 diff --git a/hsmd/hsmd.c b/hsmd/hsmd.c index 002d248ab..ae7c8d1ea 100644 --- a/hsmd/hsmd.c +++ b/hsmd/hsmd.c @@ -685,6 +685,7 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c) case WIRE_HSMD_SIGN_ANY_DELAYED_PAYMENT_TO_US: case WIRE_HSMD_SIGN_ANY_REMOTE_HTLC_TO_US: case WIRE_HSMD_SIGN_ANY_LOCAL_HTLC_TX: + case WIRE_HSMD_SIGN_ANCHORSPEND: /* Hand off to libhsmd for processing */ return req_reply(conn, c, take(hsmd_handle_client_message( @@ -718,6 +719,7 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c) case WIRE_HSMD_PREAPPROVE_INVOICE_REPLY: case WIRE_HSMD_PREAPPROVE_KEYSEND_REPLY: case WIRE_HSMD_CHECK_PUBKEY_REPLY: + case WIRE_HSMD_SIGN_ANCHORSPEND_REPLY: return bad_req_fmt(conn, c, c->msg_in, "Received an incoming message of type %s, " "which is not a request", diff --git a/hsmd/hsmd_wire.csv b/hsmd/hsmd_wire.csv index fc649bcc6..96bfe84b6 100644 --- a/hsmd/hsmd_wire.csv +++ b/hsmd/hsmd_wire.csv @@ -332,6 +332,16 @@ msgdata,hsmd_check_pubkey,pubkey,pubkey, msgtype,hsmd_check_pubkey_reply,128 msgdata,hsmd_check_pubkey_reply,ok,bool, +msgtype,hsmd_sign_anchorspend,147 +msgdata,hsmd_sign_anchorspend,peerid,node_id, +msgdata,hsmd_sign_anchorspend,channel_dbid,u64, +msgdata,hsmd_sign_anchorspend,num_inputs,u16, +msgdata,hsmd_sign_anchorspend,inputs,utxo,num_inputs +msgdata,hsmd_sign_anchorspend,psbt,wally_psbt, + +msgtype,hsmd_sign_anchorspend_reply,148 +msgdata,hsmd_sign_anchorspend_reply,psbt,wally_psbt, + # These are where lightningd asks for signatures on onchaind's behalf. msgtype,hsmd_sign_any_delayed_payment_to_us,142 msgdata,hsmd_sign_any_delayed_payment_to_us,commit_num,u64, diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c index f516e8a31..304521c0a 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -128,6 +128,7 @@ bool hsmd_check_client_capabilities(struct hsmd_client *client, case WIRE_HSMD_SIGN_ANY_DELAYED_PAYMENT_TO_US: case WIRE_HSMD_SIGN_ANY_REMOTE_HTLC_TO_US: case WIRE_HSMD_SIGN_ANY_LOCAL_HTLC_TX: + case WIRE_HSMD_SIGN_ANCHORSPEND: return (client->capabilities & HSM_CAP_MASTER) != 0; /*~ These are messages sent by the HSM so we should never receive them. */ @@ -161,6 +162,7 @@ bool hsmd_check_client_capabilities(struct hsmd_client *client, case WIRE_HSMD_PREAPPROVE_KEYSEND_REPLY: case WIRE_HSMD_DERIVE_SECRET_REPLY: case WIRE_HSMD_CHECK_PUBKEY_REPLY: + case WIRE_HSMD_SIGN_ANCHORSPEND_REPLY: break; } return false; @@ -1461,6 +1463,47 @@ static u8 *handle_sign_any_penalty_to_us(struct hsmd_client *c, const u8 *msg_in &revocation_secret, tx, wscript); } +/*~ Called from lightningd */ +static u8 *handle_sign_anchorspend(struct hsmd_client *c, const u8 *msg_in) +{ + struct node_id peer_id; + u64 dbid; + struct utxo **utxos; + struct wally_psbt *psbt; + struct secret seed; + struct pubkey local_funding_pubkey; + struct secrets secrets; + int ret; + + /* FIXME: Check output goes to us. */ + if (!fromwire_hsmd_sign_anchorspend(tmpctx, msg_in, + &peer_id, &dbid, &utxos, &psbt)) + return hsmd_status_malformed_request(c, msg_in); + + /* Sign all the UTXOs */ + sign_our_inputs(utxos, psbt); + + get_channel_seed(&peer_id, dbid, &seed); + derive_basepoints(&seed, &local_funding_pubkey, NULL, &secrets, NULL); + + tal_wally_start(); + ret = wally_psbt_sign(psbt, secrets.funding_privkey.secret.data, + sizeof(secrets.funding_privkey.secret.data), + EC_FLAG_GRIND_R); + tal_wally_end(psbt); + if (ret != WALLY_OK) { + hsmd_status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Received wally_err attempting to " + "sign anchor key %s. PSBT: %s", + type_to_string(tmpctx, struct pubkey, + &local_funding_pubkey), + type_to_string(tmpctx, struct wally_psbt, + psbt)); + } + + return towire_hsmd_sign_anchorspend_reply(NULL, psbt); +} + /*~ This is another lightningd-only interface; signing a commit transaction. * This is dangerous, since if we sign a revoked commitment tx we'll lose * funds, thus it's only available to lightningd. @@ -1864,6 +1907,8 @@ u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client, return handle_sign_any_local_htlc_tx(client, msg); case WIRE_HSMD_SIGN_ANY_PENALTY_TO_US: return handle_sign_any_penalty_to_us(client, msg); + case WIRE_HSMD_SIGN_ANCHORSPEND: + return handle_sign_anchorspend(client, msg); case WIRE_HSMD_DEV_MEMLEAK: case WIRE_HSMD_ECDH_RESP: @@ -1894,6 +1939,7 @@ u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client, case WIRE_HSMD_PREAPPROVE_INVOICE_REPLY: case WIRE_HSMD_PREAPPROVE_KEYSEND_REPLY: case WIRE_HSMD_CHECK_PUBKEY_REPLY: + case WIRE_HSMD_SIGN_ANCHORSPEND_REPLY: break; } return hsmd_status_bad_request(client, msg, "Unknown request"); @@ -1907,7 +1953,11 @@ u8 *hsmd_init(struct secret hsm_secret, u32 salt = 0; struct ext_key master_extkey, child_extkey; struct node_id node_id; - static const u32 capabilities[] = { WIRE_HSMD_CHECK_PUBKEY, WIRE_HSMD_SIGN_ANY_DELAYED_PAYMENT_TO_US }; + static const u32 capabilities[] = { + WIRE_HSMD_CHECK_PUBKEY, + WIRE_HSMD_SIGN_ANY_DELAYED_PAYMENT_TO_US, + WIRE_HSMD_SIGN_ANCHORSPEND, + }; /*~ Don't swap this. */ sodium_mlock(secretstuff.hsm_secret.data,