Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hsmd: add explicit hsmd_revoke_commitment_tx #103

Open
wants to merge 3 commits into
base: 2024-01-unilateral-close-info-anchors
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions channeld/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ CHANNELD_COMMON_OBJS := \
common/status_wiregen.o \
common/gossip_store.o \
common/hmac.o \
common/hsm_capable.o \
common/interactivetx.o \
common/htlc_state.o \
common/htlc_trim.o \
Expand Down
42 changes: 36 additions & 6 deletions channeld/channeld.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include <common/billboard.h>
#include <common/ecdh_hsmd.h>
#include <common/gossip_store.h>
#include <common/hsm_capable.h>
#include <common/hsm_version.h>
#include <common/interactivetx.h>
#include <common/key_derive.h>
#include <common/memleak.h>
Expand Down Expand Up @@ -77,6 +79,9 @@ struct peer {
/* Features we support. */
struct feature_set *our_features;

/* What (additional) messages the HSM accepts */
u32 *hsm_capabilities;

/* Tolerable amounts for feerate (only relevant for fundee). */
u32 feerate_min, feerate_max;

Expand Down Expand Up @@ -1920,6 +1925,7 @@ static void send_revocation(struct peer *peer,
const struct failed_htlc **failed;
struct added_htlc *added;
const u8 *msg;
const u8 *msg2;
const u8 *msg_for_master;

/* Marshall it now before channel_sending_revoke_and_ack changes htlcs */
Expand All @@ -1931,11 +1937,6 @@ static void send_revocation(struct peer *peer,
&failed,
&added);

/* Revoke previous commit, get new point. */
msg = make_revocation_msg_from_secret(peer, peer->next_index[LOCAL]-1,
&peer->next_local_per_commit,
old_secret, next_point);

/* From now on we apply changes to the next commitment */
peer->next_index[LOCAL]++;

Expand Down Expand Up @@ -1966,6 +1967,30 @@ static void send_revocation(struct peer *peer,

peer->splice_state->await_commitment_succcess = false;

/* Now that the master has persisted the new commitment advance the HSMD
* and fetch the revocation secret for the old one. */
struct secret old_secret2;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider removing these additional variables and just use old_secret and next_point everywhere below

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is the originals are:

			    const struct secret *old_secret,
			    const struct pubkey *next_point,

struct pubkey next_point2;
if (HSM_MAX_VERSION < 5 ||
!hsm_is_capable(peer->hsm_capabilities, WIRE_HSMD_REVOKE_COMMITMENT_TX)) {
/* Prior to HSM_VERSION 5 we use the old_secret
* received earlier from validate_commitment_tx. */
memcpy(&old_secret2, old_secret, sizeof(old_secret2));
memcpy(&next_point2, next_point, sizeof(next_point2));
} else {
msg2 = towire_hsmd_revoke_commitment_tx(tmpctx, peer->next_index[LOCAL] - 2);
msg2 = hsm_req(tmpctx, take(msg2));
if (!fromwire_hsmd_revoke_commitment_tx_reply(msg2, &old_secret2, &next_point2))
status_failed(STATUS_FAIL_HSM_IO,
"Reading revoke_commitment_tx reply: %s",
tal_hex(tmpctx, msg2));
}

/* Revoke previous commit, get new point. */
msg = make_revocation_msg_from_secret(peer, peer->next_index[LOCAL]-2,
&peer->next_local_per_commit,
&old_secret2, &next_point2);

/* Now we can finally send revoke_and_ack to peer */
peer_write(peer->pps, take(msg));
}
Expand Down Expand Up @@ -2270,7 +2295,11 @@ static struct commitsig_info *handle_peer_commit_sig(struct peer *peer,
tal_steal(commitsigs, result);
}

assert(old_secret);
// If the HSM doesn't support WIRE_HSMD_REVOKE_COMMITMENT_TX we'd better
// have the old_secret at this point.
if (HSM_MAX_VERSION < 5 ||
!hsm_is_capable(peer->hsm_capabilities, WIRE_HSMD_REVOKE_COMMITMENT_TX))
Comment on lines +2300 to +2301
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mh this is just a comment for a future improvement. Would be nice to have a method to avoid checking the version here, but with the current enum system for the hsm_capabilities this seems hard

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure if we can hack around the hsmd_check_client_capabilities

assert(old_secret);

send_revocation(peer, &commit_sig, htlc_sigs, changed_htlcs, txs[0],
old_secret, &next_point, commitsigs);
Expand Down Expand Up @@ -6085,6 +6114,7 @@ static void init_channel(struct peer *peer)
if (!fromwire_channeld_init(peer, msg,
&chainparams,
&peer->our_features,
&peer->hsm_capabilities,
&peer->channel_id,
&funding,
&funding_sats,
Expand Down
2 changes: 2 additions & 0 deletions channeld/channeld_wire.csv
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
msgtype,channeld_init,1000
msgdata,channeld_init,chainparams,chainparams,
msgdata,channeld_init,our_features,feature_set,
msgdata,channeld_init,num_hsm_capabilities,u16,
msgdata,channeld_init,hsm_capabilities,u32,num_hsm_capabilities
msgdata,channeld_init,channel_id,channel_id,
msgdata,channeld_init,funding,bitcoin_outpoint,
msgdata,channeld_init,funding_satoshi,amount_sat,
Expand Down
1 change: 1 addition & 0 deletions common/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ COMMON_SRC_NOGEN := \
common/gossmap.c \
common/hash_u5.c \
common/hmac.c \
common/hsm_capable.c \
common/hsm_encryption.c \
common/htlc_state.c \
common/htlc_trim.c \
Expand Down
13 changes: 13 additions & 0 deletions common/hsm_capable.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include "config.h"
#include <common/hsm_capable.h>

/* Is this capability supported by the HSM? (So far, always a message
* number) */
bool hsm_is_capable(u32 *capabilities, u32 msgtype)
{
for (size_t i = 0; i < tal_count(capabilities); i++) {
if (capabilities[i] == msgtype)
return true;
}
return false;
}
11 changes: 11 additions & 0 deletions common/hsm_capable.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#ifndef LIGHTNING_COMMON_HSM_CAPABLE_H
#define LIGHTNING_COMMON_HSM_CAPABLE_H
#include "config.h"
#include <ccan/short_types/short_types.h>
#include <ccan/tal/tal.h>
#include <stdbool.h>

/* Is this capability supported by the HSM? (So far, always a message
* number) */
bool hsm_is_capable(u32 *capabilities, u32 msgtype);
#endif /* LIGHTNING_COMMON_HSM_CAPABLE_H */
2 changes: 1 addition & 1 deletion common/hsm_version.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@
* v4 with buried outpoint check: f44fae666895cab0347b3de7c245267c71cc7de834827b83e286e86318c08aec
*/
#define HSM_MIN_VERSION 3
#define HSM_MAX_VERSION 4
#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 @@ -650,6 +650,7 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c)
case WIRE_HSMD_FORGET_CHANNEL:
case WIRE_HSMD_SIGN_COMMITMENT_TX:
case WIRE_HSMD_VALIDATE_COMMITMENT_TX:
case WIRE_HSMD_REVOKE_COMMITMENT_TX:
case WIRE_HSMD_VALIDATE_REVOCATION:
case WIRE_HSMD_SIGN_PENALTY_TO_US:
case WIRE_HSMD_SIGN_REMOTE_COMMITMENT_TX:
Expand Down Expand Up @@ -705,6 +706,7 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c)
case WIRE_HSMSTATUS_CLIENT_BAD_REQUEST:
case WIRE_HSMD_SIGN_COMMITMENT_TX_REPLY:
case WIRE_HSMD_VALIDATE_COMMITMENT_TX_REPLY:
case WIRE_HSMD_REVOKE_COMMITMENT_TX_REPLY:
case WIRE_HSMD_VALIDATE_REVOCATION_REPLY:
case WIRE_HSMD_SIGN_TX_REPLY:
case WIRE_HSMD_SIGN_OPTION_WILL_FUND_OFFER_REPLY:
Expand Down
8 changes: 8 additions & 0 deletions hsmd/hsmd_wire.csv
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,14 @@ msgtype,hsmd_validate_commitment_tx_reply,135
msgdata,hsmd_validate_commitment_tx_reply,old_commitment_secret,?secret,
msgdata,hsmd_validate_commitment_tx_reply,next_per_commitment_point,pubkey,

# Revoke our local commitment, returns the revocation secret and next point
msgtype,hsmd_revoke_commitment_tx,40
msgdata,hsmd_revoke_commitment_tx,commit_num,u64,

msgtype,hsmd_revoke_commitment_tx_reply,140
msgdata,hsmd_revoke_commitment_tx_reply,old_commitment_secret,secret,
msgdata,hsmd_revoke_commitment_tx_reply,next_per_commitment_point,pubkey,

# Vaidate the counterparty's revocation secret
msgtype,hsmd_validate_revocation,36
msgdata,hsmd_validate_revocation,revoke_num,u64,
Expand Down
47 changes: 46 additions & 1 deletion hsmd/libhsmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ bool hsmd_check_client_capabilities(struct hsmd_client *client,
case WIRE_HSMD_SIGN_REMOTE_COMMITMENT_TX:
case WIRE_HSMD_SIGN_REMOTE_HTLC_TX:
case WIRE_HSMD_VALIDATE_COMMITMENT_TX:
case WIRE_HSMD_REVOKE_COMMITMENT_TX:
case WIRE_HSMD_VALIDATE_REVOCATION:
return (client->capabilities & HSM_PERM_SIGN_REMOTE_TX) != 0;

Expand Down Expand Up @@ -160,6 +161,7 @@ bool hsmd_check_client_capabilities(struct hsmd_client *client,
case WIRE_HSMSTATUS_CLIENT_BAD_REQUEST:
case WIRE_HSMD_SIGN_COMMITMENT_TX_REPLY:
case WIRE_HSMD_VALIDATE_COMMITMENT_TX_REPLY:
case WIRE_HSMD_REVOKE_COMMITMENT_TX_REPLY:
case WIRE_HSMD_VALIDATE_REVOCATION_REPLY:
case WIRE_HSMD_SIGN_TX_REPLY:
case WIRE_HSMD_SIGN_OPTION_WILL_FUND_OFFER_REPLY:
Expand Down Expand Up @@ -1696,6 +1698,46 @@ static u8 *handle_validate_commitment_tx(struct hsmd_client *c, const u8 *msg_in

/* Stub implementation */

/* The signatures are not checked in this stub because they
* are already checked by the caller. However, the returned
* old_secret and next_per_commitment_point are used.
*/

get_channel_seed(&c->id, c->dbid, &channel_seed);
if (!derive_shaseed(&channel_seed, &shaseed))
return hsmd_status_bad_request(c, msg_in, "bad derive_shaseed");

if (!per_commit_point(&shaseed, &next_per_commitment_point, commit_num + 1))
return hsmd_status_bad_request_fmt(
c, msg_in, "bad per_commit_point %" PRIu64, commit_num + 1);

/* Don't ever return the old_secret here anymore. The node should
* call hsmd_revoke_commitment_tx to transactionally revoke the commitment
* and return the secret ...
*/
old_secret = NULL;

return towire_hsmd_validate_commitment_tx_reply(
NULL, old_secret, &next_per_commitment_point);
}

/* ~This stub implementation is overriden by fully validating signers
* that need to independently revoke the old local commitment tx and
* release it's secret
*/
static u8 *handle_revoke_commitment_tx(struct hsmd_client *c, const u8 *msg_in)
{
u64 commit_num;
struct secret channel_seed;
struct sha256 shaseed;
struct secret *old_secret;
struct pubkey next_per_commitment_point;

if (!fromwire_hsmd_revoke_commitment_tx(msg_in, &commit_num))
return hsmd_status_malformed_request(c, msg_in);

/* Stub implementation */

/* The signatures are not checked in this stub because they
* are already checked by the caller. However, the returned
* old_secret and next_per_commitment_point are used.
Expand All @@ -1719,7 +1761,7 @@ static u8 *handle_validate_commitment_tx(struct hsmd_client *c, const u8 *msg_in
old_secret = NULL;
}

return towire_hsmd_validate_commitment_tx_reply(
return towire_hsmd_revoke_commitment_tx_reply(
NULL, old_secret, &next_per_commitment_point);
}

Expand Down Expand Up @@ -2010,6 +2052,8 @@ u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client,
return handle_sign_commitment_tx(client, msg);
case WIRE_HSMD_VALIDATE_COMMITMENT_TX:
return handle_validate_commitment_tx(client, msg);
case WIRE_HSMD_REVOKE_COMMITMENT_TX:
return handle_revoke_commitment_tx(client, msg);
case WIRE_HSMD_VALIDATE_REVOCATION:
return handle_validate_revocation(client, msg);
case WIRE_HSMD_SIGN_REMOTE_HTLC_TO_US:
Expand Down Expand Up @@ -2052,6 +2096,7 @@ u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client,
case WIRE_HSMSTATUS_CLIENT_BAD_REQUEST:
case WIRE_HSMD_SIGN_COMMITMENT_TX_REPLY:
case WIRE_HSMD_VALIDATE_COMMITMENT_TX_REPLY:
case WIRE_HSMD_REVOKE_COMMITMENT_TX_REPLY:
case WIRE_HSMD_VALIDATE_REVOCATION_REPLY:
case WIRE_HSMD_SIGN_TX_REPLY:
case WIRE_HSMD_SIGN_OPTION_WILL_FUND_OFFER_REPLY:
Expand Down
1 change: 1 addition & 0 deletions lightningd/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ LIGHTNINGD_COMMON_OBJS := \
common/status_wiregen.o \
common/hash_u5.o \
common/hmac.o \
common/hsm_capable.o \
common/hsm_encryption.o \
common/htlc_state.o \
common/htlc_trim.o \
Expand Down
3 changes: 3 additions & 0 deletions lightningd/channel_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -1626,6 +1626,9 @@ bool peer_start_channeld(struct channel *channel,
initmsg = towire_channeld_init(tmpctx,
chainparams,
ld->our_features,
/* Capabilities arg needs to be a tal array */
tal_dup_arr(tmpctx, u32, ld->hsm_capabilities,
tal_count(ld->hsm_capabilities), 0),
&channel->cid,
&channel->funding,
channel->funding_sats,
Expand Down
7 changes: 2 additions & 5 deletions lightningd/hsm_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <ccan/fdpass/fdpass.h>
#include <common/ecdh.h>
#include <common/errcode.h>
#include <common/hsm_capable.h>
#include <common/hsm_encryption.h>
#include <common/hsm_version.h>
#include <common/invoice_path_id.h>
Expand Down Expand Up @@ -78,11 +79,7 @@ static unsigned int hsm_msg(struct subd *hsmd,
* number) */
bool hsm_capable(struct lightningd *ld, u32 msgtype)
{
for (size_t i = 0; i < tal_count(ld->hsm_capabilities); i++) {
if (ld->hsm_capabilities[i] == msgtype)
return true;
}
return false;
return hsm_is_capable(ld->hsm_capabilities, msgtype);
}

struct ext_key *hsm_init(struct lightningd *ld)
Expand Down
1 change: 1 addition & 0 deletions wallet/test/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ WALLET_TEST_COMMON_OBJS := \
common/derive_basepoints.o \
common/features.o \
common/htlc_state.o \
common/hsm_capable.o \
common/htlc_wire.o \
common/fee_states.o \
common/type_to_string.o \
Expand Down
Loading