hsm: sign funding transactions.

The main daemon gives it to us to sign the inputs.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2017-02-21 15:15:29 +10:30
parent 891a915e0f
commit f66445c1d1
2 changed files with 104 additions and 4 deletions

View File

@ -1,5 +1,7 @@
#include <bitcoin/privkey.h>
#include <bitcoin/pubkey.h>
#include <bitcoin/script.h>
#include <bitcoin/tx.h>
#include <ccan/breakpoint/breakpoint.h>
#include <ccan/container_of/container_of.h>
#include <ccan/crypto/hkdf_sha256/hkdf_sha256.h>
@ -8,6 +10,7 @@
#include <ccan/io/fdpass/fdpass.h>
#include <ccan/io/io.h>
#include <ccan/noerr/noerr.h>
#include <ccan/ptrint/ptrint.h>
#include <ccan/read_write_all/read_write_all.h>
#include <errno.h>
#include <fcntl.h>
@ -16,6 +19,7 @@
#include <lightningd/hsm/gen_hsm_client_wire.h>
#include <lightningd/hsm/gen_hsm_control_wire.h>
#include <lightningd/hsm/gen_hsm_status_wire.h>
#include <permute_tx.h>
#include <secp256k1_ecdh.h>
#include <sodium/randombytes.h>
#include <status.h>
@ -198,7 +202,7 @@ static void populate_secretstuff(void)
"Can't derive private bip32 key");
}
static inline void bitcoin_pubkey(struct pubkey *pubkey, u32 index)
static void bitcoin_pubkey(struct pubkey *pubkey, u32 index)
{
struct ext_key ext;
@ -217,9 +221,9 @@ static inline void bitcoin_pubkey(struct pubkey *pubkey, u32 index)
"Parse of BIP32 child %u pubkey failed", index);
}
static inline void bitcoin_keypair(struct privkey *privkey,
struct pubkey *pubkey,
u32 index)
static void bitcoin_keypair(struct privkey *privkey,
struct pubkey *pubkey,
u32 index)
{
struct ext_key ext;
@ -340,6 +344,82 @@ static u8 *pass_hsmfd_ecdh(struct io_conn *conn,
return towire_hsmctl_hsmfd_fd_response(control);
}
/* Note that it's the main daemon that asks for the funding signature so it
* can broadcast it. */
static u8 *sign_funding_tx(const tal_t *ctx, const u8 *data)
{
const tal_t *tmpctx = tal_tmpctx(ctx);
u64 satoshi_out, change_out;
u32 change_keyindex;
struct privkey local_privkey;
struct pubkey local_pubkey, remote_pubkey;
struct utxo *inputs;
struct bitcoin_tx *tx;
u8 *wscript, *msg_out;
secp256k1_ecdsa_signature *sig;
const void **inmap;
size_t i;
/* FIXME: Check fee is "reasonable" */
if (!fromwire_hsmctl_sign_funding(tmpctx, data, NULL,
&satoshi_out, &change_out,
&change_keyindex, &local_privkey,
&local_pubkey, &inputs))
status_failed(WIRE_HSMSTATUS_BAD_REQUEST, "Bad SIGN_FUNDING");
if (!secp256k1_ec_pubkey_create(secp256k1_ctx,
&local_pubkey.pubkey,
local_privkey.secret))
status_failed(WIRE_HSMSTATUS_BAD_REQUEST,
"Bad SIGN_FUNDING privkey");
tx = bitcoin_tx(tmpctx, tal_count(inputs), 1 + !!change_out);
inmap = tal_arr(tmpctx, const void *, tal_count(inputs));
for (i = 0; i < tal_count(inputs); i++) {
tx->input[i].txid = inputs[i].txid;
tx->input[i].index = inputs[i].outnum;
tx->input[i].amount = tal_dup(tx->input, u64, &inputs[i].amount);
inmap[i] = int2ptr(i);
}
tx->output[0].amount = satoshi_out;
wscript = bitcoin_redeem_2of2(tx, &local_pubkey, &remote_pubkey);
tx->output[0].script = scriptpubkey_p2wsh(tx, wscript);
if (change_out) {
struct pubkey changekey;
bitcoin_pubkey(&changekey, change_keyindex);
tx->output[1].amount = change_out;
tx->output[1].script = scriptpubkey_p2wpkh(tx, &changekey);
}
/* Now permute. */
permute_outputs(tx->output, tal_count(tx->output), NULL);
permute_inputs(tx->input, tal_count(tx->input), inmap);
/* Now generate signatures. */
sig = tal_arr(tmpctx, secp256k1_ecdsa_signature, tal_count(inputs));
for (i = 0; i < tal_count(inputs); i++) {
struct pubkey inkey;
struct privkey inprivkey;
const struct utxo *in = &inputs[ptr2int(inmap[i])];
u8 *subscript;
bitcoin_keypair(&inprivkey, &inkey, in->keyindex);
if (in->is_p2sh)
subscript = bitcoin_redeem_p2wpkh(tmpctx, &inkey);
else
subscript = NULL;
wscript = p2wpkh_scriptcode(tmpctx, &inkey);
sign_tx_input(tx, i, subscript, wscript,
&inprivkey, &inkey, &sig[i]);
}
msg_out = towire_hsmctl_sign_funding_response(ctx, sig);
tal_free(tmpctx);
return msg_out;
}
static struct io_plan *control_received_req(struct io_conn *conn,
struct conn_info *control)
{
@ -359,9 +439,13 @@ static struct io_plan *control_received_req(struct io_conn *conn,
control->out = pass_hsmfd_ecdh(conn, control, control->in,
&control->out_fd);
goto send_out;
case WIRE_HSMCTL_SIGN_FUNDING:
control->out = sign_funding_tx(control, control->in);
goto send_out;
case WIRE_HSMCTL_INIT_RESPONSE:
case WIRE_HSMCTL_HSMFD_FD_RESPONSE:
case WIRE_HSMCTL_SIGN_FUNDING_RESPONSE:
break;
}

View File

@ -11,5 +11,21 @@ hsmctl_init_response,35,bip32_seed,bip32_len*1,u8
hsmctl_hsmfd_ecdh,3
hsmctl_hsmfd_ecdh,0,unique_id,8
# Return signature for a funding tx.
#include <lightningd/utxo.h>
# FIXME: This should also take their commit sig & details, to verify.
hsmctl_sign_funding,4
hsmctl_sign_funding,0,satoshi_out,8
hsmctl_sign_funding,8,change_out,8
hsmctl_sign_funding,16,change_keyindex,4
hsmctl_sign_funding,20,our_privkey,32,struct privkey
hsmctl_sign_funding,52,their_pubkey,33
hsmctl_sign_funding,85,num_inputs,2
hsmctl_sign_funding,87,inputs,num_inputs*49,struct utxo
hsmctl_sign_funding_response,104
hsmctl_sign_funding_response,0,num_sigs,2
hsmctl_sign_funding_response,0,sig,num_sigs*64,secp256k1_ecdsa_signature
# No message, just an fd.
hsmctl_hsmfd_fd_response,103