mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 21:35:11 +01:00
hsmd: add routines to sign onchain transactions, part 1.
This handles the "to-us" transactions which return funds to the wallet. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
93b8217eb0
commit
dfaf74d972
@ -76,7 +76,7 @@ $(LIGHTNINGD_GOSSIP_CONTROL_OBJS) : $(LIGHTNINGD_GOSSIP_CONTROL_HEADERS)
|
||||
|
||||
gossipd-all: lightningd/lightning_gossipd $(LIGHTNINGD_GOSSIP_CLIENT_OBJS)
|
||||
|
||||
lightningd/lightning_gossipd: $(LIGHTNINGD_GOSSIP_OBJS) $(GOSSIPD_COMMON_OBJS) $(BITCOIN_OBJS) $(WIRE_OBJS)
|
||||
lightningd/lightning_gossipd: $(LIGHTNINGD_GOSSIP_OBJS) $(GOSSIPD_COMMON_OBJS) $(BITCOIN_OBJS) $(WIRE_OBJS) $(LIGHTNINGD_HSM_CLIENT_OBJS)
|
||||
|
||||
gossipd/gen_gossip_wire.h: $(WIRE_GEN) gossipd/gossip_wire.csv
|
||||
$(WIRE_GEN) --header $@ gossip_wire_type < gossipd/gossip_wire.csv > $@
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#define HSM_CAP_ECDH 1
|
||||
#define HSM_CAP_SIGN_GOSSIP 2
|
||||
#define HSM_CAP_SIGN_ONCHAIN_TX 4
|
||||
|
||||
#define HSM_CAP_MASTER 1024
|
||||
#endif /* LIGHTNING_HSMD_CAPABILITIES_H */
|
||||
|
183
hsmd/hsm.c
183
hsmd/hsm.c
@ -14,6 +14,7 @@
|
||||
#include <ccan/ptrint/ptrint.h>
|
||||
#include <ccan/read_write_all/read_write_all.h>
|
||||
#include <ccan/take/take.h>
|
||||
#include <ccan/tal/str/str.h>
|
||||
#include <common/daemon_conn.h>
|
||||
#include <common/derive_basepoints.h>
|
||||
#include <common/funding_tx.h>
|
||||
@ -315,6 +316,172 @@ static struct io_plan *handle_sign_commitment_tx(struct io_conn *conn,
|
||||
return daemon_conn_read_next(conn, dc);
|
||||
}
|
||||
|
||||
static PRINTF_FMT(3,4)
|
||||
struct io_plan *bad_sign_request(struct io_conn *conn,
|
||||
struct client *c,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char *str;
|
||||
|
||||
va_start(ap, fmt);
|
||||
str = tal_fmt(tmpctx, fmt, ap);
|
||||
status_broken("Client %s bad sign request: %s",
|
||||
type_to_string(tmpctx, struct pubkey, &c->id), str);
|
||||
va_end(ap);
|
||||
|
||||
daemon_conn_send(c->master,
|
||||
take(towire_hsmstatus_client_bad_request(NULL,
|
||||
&c->id,
|
||||
c->dc.msg_in)));
|
||||
return io_close(conn);
|
||||
}
|
||||
|
||||
/* FIXME: Derive output address for this client, and check it here! */
|
||||
static struct io_plan *handle_sign_to_us_tx(struct io_conn *conn,
|
||||
struct client *c,
|
||||
struct bitcoin_tx *tx,
|
||||
const struct privkey *privkey,
|
||||
const u8 *wscript,
|
||||
u64 input_amount)
|
||||
{
|
||||
secp256k1_ecdsa_signature sig;
|
||||
struct pubkey pubkey;
|
||||
|
||||
if (!pubkey_from_privkey(privkey, &pubkey))
|
||||
return bad_sign_request(conn, c, "bad pubkey_from_privkey");
|
||||
|
||||
if (tal_count(tx->input) != 1)
|
||||
return bad_sign_request(conn, c, "bad txinput count");
|
||||
|
||||
tx->input[0].amount = tal_dup(tx->input, u64, &input_amount);
|
||||
sign_tx_input(tx, 0, NULL, wscript, privkey, &pubkey, &sig);
|
||||
|
||||
daemon_conn_send(&c->dc, take(towire_hsm_sign_tx_reply(NULL, &sig)));
|
||||
return daemon_conn_read_next(conn, &c->dc);
|
||||
}
|
||||
|
||||
static struct io_plan *handle_sign_delayed_payment_to_us(struct io_conn *conn,
|
||||
struct client *c)
|
||||
{
|
||||
u64 commit_num, input_amount;
|
||||
struct secret channel_seed, basepoint_secret;
|
||||
struct pubkey basepoint;
|
||||
struct bitcoin_tx *tx;
|
||||
struct sha256 shaseed;
|
||||
struct pubkey per_commitment_point;
|
||||
struct privkey privkey;
|
||||
u8 *wscript;
|
||||
|
||||
if (!fromwire_hsm_sign_delayed_payment_to_us(tmpctx, c->dc.msg_in,
|
||||
&commit_num,
|
||||
&tx, &wscript,
|
||||
&input_amount))
|
||||
return bad_sign_request(conn, c,
|
||||
"malformed hsm_sign_delayed_payment");
|
||||
|
||||
get_channel_seed(&c->id, c->dbid, &channel_seed);
|
||||
|
||||
if (!derive_shaseed(&channel_seed, &shaseed))
|
||||
return bad_sign_request(conn, c, "bad derive_shaseed");
|
||||
|
||||
if (!per_commit_point(&shaseed, &per_commitment_point, commit_num))
|
||||
return bad_sign_request(conn, c,
|
||||
"bad per_commitment_point %"PRIu64,
|
||||
commit_num);
|
||||
|
||||
if (!derive_delayed_payment_basepoint(&channel_seed,
|
||||
&basepoint,
|
||||
&basepoint_secret))
|
||||
return bad_sign_request(conn, c, "failed deriving basepoint");
|
||||
|
||||
if (!derive_simple_privkey(&basepoint_secret,
|
||||
&basepoint,
|
||||
&per_commitment_point,
|
||||
&privkey))
|
||||
return bad_sign_request(conn, c, "failed deriving privkey");
|
||||
|
||||
return handle_sign_to_us_tx(conn, c, tx, &privkey, wscript,
|
||||
input_amount);
|
||||
}
|
||||
|
||||
static struct io_plan *handle_sign_remote_htlc_to_us(struct io_conn *conn,
|
||||
struct client *c)
|
||||
{
|
||||
u64 input_amount;
|
||||
struct secret channel_seed, htlc_basepoint_secret;
|
||||
struct pubkey htlc_basepoint;
|
||||
struct bitcoin_tx *tx;
|
||||
struct pubkey remote_per_commitment_point;
|
||||
struct privkey privkey;
|
||||
u8 *wscript;
|
||||
|
||||
if (!fromwire_hsm_sign_remote_htlc_to_us(tmpctx, c->dc.msg_in,
|
||||
&remote_per_commitment_point,
|
||||
&tx, &wscript,
|
||||
&input_amount))
|
||||
return bad_sign_request(conn, c,
|
||||
"malformed hsm_sign_remote_htlc_to_us");
|
||||
|
||||
get_channel_seed(&c->id, c->dbid, &channel_seed);
|
||||
|
||||
if (!derive_htlc_basepoint(&channel_seed, &htlc_basepoint,
|
||||
&htlc_basepoint_secret))
|
||||
return bad_sign_request(conn, c,
|
||||
"Failed derive_htlc_basepoint");
|
||||
|
||||
if (!derive_simple_privkey(&htlc_basepoint_secret,
|
||||
&htlc_basepoint,
|
||||
&remote_per_commitment_point,
|
||||
&privkey))
|
||||
return bad_sign_request(conn, c,
|
||||
"Failed deriving htlc privkey");
|
||||
|
||||
return handle_sign_to_us_tx(conn, c, tx, &privkey, wscript,
|
||||
input_amount);
|
||||
}
|
||||
|
||||
static struct io_plan *handle_sign_penalty_to_us(struct io_conn *conn,
|
||||
struct client *c)
|
||||
{
|
||||
u64 input_amount;
|
||||
struct secret channel_seed, revocation_secret, revocation_basepoint_secret;
|
||||
struct pubkey revocation_basepoint;
|
||||
struct bitcoin_tx *tx;
|
||||
struct pubkey point;
|
||||
struct privkey privkey;
|
||||
u8 *wscript;
|
||||
|
||||
if (!fromwire_hsm_sign_penalty_to_us(tmpctx, c->dc.msg_in,
|
||||
&revocation_secret,
|
||||
&tx, &wscript,
|
||||
&input_amount))
|
||||
return bad_sign_request(conn, c,
|
||||
"malformed hsm_sign_penalty_to_us");
|
||||
|
||||
if (!pubkey_from_secret(&revocation_secret, &point))
|
||||
return bad_sign_request(conn, c,
|
||||
"Failed deriving pubkey");
|
||||
|
||||
get_channel_seed(&c->id, c->dbid, &channel_seed);
|
||||
if (!derive_revocation_basepoint(&channel_seed,
|
||||
&revocation_basepoint,
|
||||
&revocation_basepoint_secret))
|
||||
return bad_sign_request(conn, c,
|
||||
"Failed deriving revocation basepoint");
|
||||
|
||||
if (!derive_revocation_privkey(&revocation_basepoint_secret,
|
||||
&revocation_secret,
|
||||
&revocation_basepoint,
|
||||
&point,
|
||||
&privkey))
|
||||
return bad_sign_request(conn, c,
|
||||
"Failed deriving revocation privkey");
|
||||
|
||||
return handle_sign_to_us_tx(conn, c, tx, &privkey, wscript,
|
||||
input_amount);
|
||||
}
|
||||
|
||||
static bool check_client_capabilities(struct client *client,
|
||||
enum hsm_client_wire_type t)
|
||||
{
|
||||
@ -327,6 +494,11 @@ static bool check_client_capabilities(struct client *client,
|
||||
case WIRE_HSM_NODE_ANNOUNCEMENT_SIG_REQ:
|
||||
return (client->capabilities & HSM_CAP_SIGN_GOSSIP) != 0;
|
||||
|
||||
case WIRE_HSM_SIGN_DELAYED_PAYMENT_TO_US:
|
||||
case WIRE_HSM_SIGN_REMOTE_HTLC_TO_US:
|
||||
case WIRE_HSM_SIGN_PENALTY_TO_US:
|
||||
return (client->capabilities & HSM_CAP_SIGN_ONCHAIN_TX) != 0;
|
||||
|
||||
case WIRE_HSM_INIT:
|
||||
case WIRE_HSM_CLIENT_HSMFD:
|
||||
case WIRE_HSM_SIGN_FUNDING:
|
||||
@ -347,6 +519,7 @@ static bool check_client_capabilities(struct client *client,
|
||||
case WIRE_HSM_INIT_REPLY:
|
||||
case WIRE_HSMSTATUS_CLIENT_BAD_REQUEST:
|
||||
case WIRE_HSM_SIGN_COMMITMENT_TX_REPLY:
|
||||
case WIRE_HSM_SIGN_TX_REPLY:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
@ -408,6 +581,15 @@ static struct io_plan *handle_client(struct io_conn *conn,
|
||||
case WIRE_HSM_SIGN_COMMITMENT_TX:
|
||||
return handle_sign_commitment_tx(conn, dc);
|
||||
|
||||
case WIRE_HSM_SIGN_DELAYED_PAYMENT_TO_US:
|
||||
return handle_sign_delayed_payment_to_us(conn, c);
|
||||
|
||||
case WIRE_HSM_SIGN_REMOTE_HTLC_TO_US:
|
||||
return handle_sign_remote_htlc_to_us(conn, c);
|
||||
|
||||
case WIRE_HSM_SIGN_PENALTY_TO_US:
|
||||
return handle_sign_penalty_to_us(conn, c);
|
||||
|
||||
case WIRE_HSM_ECDH_RESP:
|
||||
case WIRE_HSM_CANNOUNCEMENT_SIG_REPLY:
|
||||
case WIRE_HSM_CUPDATE_SIG_REPLY:
|
||||
@ -419,6 +601,7 @@ static struct io_plan *handle_client(struct io_conn *conn,
|
||||
case WIRE_HSM_INIT_REPLY:
|
||||
case WIRE_HSMSTATUS_CLIENT_BAD_REQUEST:
|
||||
case WIRE_HSM_SIGN_COMMITMENT_TX_REPLY:
|
||||
case WIRE_HSM_SIGN_TX_REPLY:
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -103,4 +103,30 @@ hsm_sign_commitment_tx,,funding_amount,u64
|
||||
hsm_sign_commitment_tx_reply,105
|
||||
hsm_sign_commitment_tx_reply,,sig,secp256k1_ecdsa_signature
|
||||
|
||||
# Onchaind asks HSM to sign a spend to-us. Four variants, since each set
|
||||
# of keys is derived differently...
|
||||
# FIXME: Have master tell hsmd the keyindex, so it can validate output!
|
||||
hsm_sign_delayed_payment_to_us,12
|
||||
hsm_sign_delayed_payment_to_us,,commit_num,u64
|
||||
hsm_sign_delayed_payment_to_us,,tx,struct bitcoin_tx
|
||||
hsm_sign_delayed_payment_to_us,,wscript_len,u16
|
||||
hsm_sign_delayed_payment_to_us,,wscript,wscript_len*u8
|
||||
hsm_sign_delayed_payment_to_us,,input_amount,u64
|
||||
|
||||
hsm_sign_remote_htlc_to_us,13
|
||||
hsm_sign_remote_htlc_to_us,,remote_per_commitment_point,struct pubkey
|
||||
hsm_sign_remote_htlc_to_us,,tx,struct bitcoin_tx
|
||||
hsm_sign_remote_htlc_to_us,,wscript_len,u16
|
||||
hsm_sign_remote_htlc_to_us,,wscript,wscript_len*u8
|
||||
hsm_sign_remote_htlc_to_us,,input_amount,u64
|
||||
|
||||
hsm_sign_penalty_to_us,14
|
||||
hsm_sign_penalty_to_us,,revocation_secret,struct secret
|
||||
hsm_sign_penalty_to_us,,tx,struct bitcoin_tx
|
||||
hsm_sign_penalty_to_us,,wscript_len,u16
|
||||
hsm_sign_penalty_to_us,,wscript,wscript_len*u8
|
||||
hsm_sign_penalty_to_us,,input_amount,u64
|
||||
|
||||
# Reply for all the above requests from onchaind.
|
||||
hsm_sign_tx_reply,112
|
||||
hsm_sign_tx_reply,,sig,secp256k1_ecdsa_signature
|
||||
|
@ -101,7 +101,7 @@ LIGHTNINGD_HEADERS_GEN = \
|
||||
ALL_GEN_HEADERS += $(LIGHTNINGD_HEADERS_GEN)
|
||||
|
||||
# All together in one convenient var
|
||||
LIGHTNINGD_HEADERS = $(LIGHTNINGD_HEADERS_NOGEN) $(LIGHTNINGD_HEADERS_GEN) $(EXTERNAL_HEADERS) $(WIRE_HEADERS) $(BITCOIN_HEADERS) $(COMMON_HEADERS) $(WALLET_LIB_HEADERS)
|
||||
LIGHTNINGD_HEADERS = $(LIGHTNINGD_HEADERS_NOGEN) $(LIGHTNINGD_HEADERS_GEN) $(EXTERNAL_HEADERS) $(WIRE_HEADERS) $(BITCOIN_HEADERS) $(COMMON_HEADERS) $(WALLET_LIB_HEADERS) $(LIGHTNINGD_HSM_CLIENT_HEADERS)
|
||||
|
||||
$(LIGHTNINGD_OBJS): $(LIGHTNINGD_HEADERS)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user