From ce845853b0d4e12f9f13ebcfd1bba927fa919d08 Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Fri, 5 Jan 2018 00:45:11 +0100 Subject: [PATCH] hsm: Generate fully signed transactions and return them to caller So far we have been generating the tx both in the HSM and in the caller, and had to rely on them generating exactly the same transaction. This makes it a lot simpler by fully signing and serializing the TX on the HSM side and the caller just needs to unpack and broadcast it. Signed-off-by: Christian Decker --- hsmd/hsm.c | 23 +++++++++++++++++------ hsmd/hsm_client_wire_csv | 3 +-- wallet/walletrpc.c | 40 +++------------------------------------- 3 files changed, 21 insertions(+), 45 deletions(-) diff --git a/hsmd/hsm.c b/hsmd/hsm.c index e2170b65e..71700e9c8 100644 --- a/hsmd/hsm.c +++ b/hsmd/hsm.c @@ -601,8 +601,8 @@ static void sign_withdrawal_tx(struct daemon_conn *master, const u8 *msg) u32 change_keyindex; struct utxo *inutxos; const struct utxo **utxos; - secp256k1_ecdsa_signature *sigs; u8 *wscript; + u8 **scriptSigs; struct bitcoin_tx *tx; struct ext_key ext; struct pubkey changekey; @@ -630,13 +630,13 @@ static void sign_withdrawal_tx(struct daemon_conn *master, const u8 *msg) tmpctx, utxos, scriptpubkey, satoshi_out, &changekey, change_out, NULL); - /* Now generate signatures. */ - sigs = tal_arr(tmpctx, secp256k1_ecdsa_signature, tal_count(utxos)); + scriptSigs = tal_arr(tmpctx, u8*, tal_count(utxos)); for (size_t i = 0; i < tal_count(utxos); i++) { struct pubkey inkey; struct privkey inprivkey; const struct utxo *in = utxos[i]; u8 *subscript; + secp256k1_ecdsa_signature sig; bitcoin_keypair(&inprivkey, &inkey, in->keyindex); if (utxos[i]->is_p2sh) @@ -645,12 +645,23 @@ static void sign_withdrawal_tx(struct daemon_conn *master, const u8 *msg) subscript = NULL; wscript = p2wpkh_scriptcode(tmpctx, &inkey); - sign_tx_input(tx, i, subscript, wscript, - &inprivkey, &inkey, &sigs[i]); + sign_tx_input(tx, i, subscript, wscript, &inprivkey, &inkey, + &sig); + + tx->input[i].witness = bitcoin_witness_p2wpkh(tx, &sig, &inkey); + + if (utxos[i]->is_p2sh) + scriptSigs[i] = bitcoin_scriptsig_p2sh_p2wpkh(tx, &inkey); + else + scriptSigs[i] = NULL; } + /* Now complete the transaction by attaching the scriptSigs where necessary */ + for (size_t i=0; iinput[i].script = scriptSigs[i]; + daemon_conn_send(master, - take(towire_hsm_sign_withdrawal_reply(tmpctx, sigs))); + take(towire_hsm_sign_withdrawal_reply(tmpctx, tx))); tal_free(tmpctx); } diff --git a/hsmd/hsm_client_wire_csv b/hsmd/hsm_client_wire_csv index db0ebada5..8f96a8e20 100644 --- a/hsmd/hsm_client_wire_csv +++ b/hsmd/hsm_client_wire_csv @@ -57,8 +57,7 @@ hsm_sign_withdrawal,,num_inputs,u16 hsm_sign_withdrawal,,inputs,num_inputs*struct utxo hsm_sign_withdrawal_reply,107 -hsm_sign_withdrawal_reply,,num_sigs,u16 -hsm_sign_withdrawal_reply,,sig,num_sigs*secp256k1_ecdsa_signature +hsm_sign_withdrawal_reply,,tx,struct bitcoin_tx # Sign an invoice hsm_sign_invoice,8 diff --git a/wallet/walletrpc.c b/wallet/walletrpc.c index d3dab05d8..0fd5270b6 100644 --- a/wallet/walletrpc.c +++ b/wallet/walletrpc.c @@ -194,9 +194,6 @@ static void json_withdraw(struct command *cmd, u32 feerate_per_kw = get_feerate(cmd->ld->topology, FEERATE_NORMAL); u64 fee_estimate; struct utxo *utxos; - struct ext_key ext; - struct pubkey changekey; - secp256k1_ecdsa_signature *sigs; struct bitcoin_tx *tx; bool withdraw_all = false; @@ -293,43 +290,12 @@ static void json_withdraw(struct command *cmd, msg = hsm_sync_read(cmd, cmd->ld); - if (!fromwire_hsm_sign_withdrawal_reply(withdraw, msg, NULL, &sigs)) + tx = tal(withdraw, struct bitcoin_tx); + + if (!fromwire_hsm_sign_withdrawal_reply(msg, NULL, tx)) fatal("HSM gave bad sign_withdrawal_reply %s", tal_hex(withdraw, msg)); - if (withdraw->changesatoshi) { - if (bip32_key_from_parent(cmd->ld->wallet->bip32_base, - withdraw->change_key_index, - BIP32_FLAG_KEY_PUBLIC, &ext) - != WALLY_OK) { - command_fail(cmd, "Changekey generation failure"); - return; - } - - pubkey_from_der(ext.pub_key, sizeof(ext.pub_key), &changekey); - } - tx = withdraw_tx(withdraw, withdraw->utxos, withdraw->destination, - withdraw->amount, &changekey, withdraw->changesatoshi, - cmd->ld->wallet->bip32_base); - - if (tal_count(sigs) != tal_count(tx->input)) - fatal("HSM gave %zu sigs, needed %zu", - tal_count(sigs), tal_count(tx->input)); - - /* Create input parts from signatures. */ - for (size_t i = 0; i < tal_count(tx->input); i++) { - struct pubkey key; - - if (!bip32_pubkey(cmd->ld->wallet->bip32_base, - &key, withdraw->utxos[i]->keyindex)) - fatal("Cannot generate BIP32 key for UTXO %u", - withdraw->utxos[i]->keyindex); - - /* P2SH inputs have same witness. */ - tx->input[i].witness - = bitcoin_witness_p2wpkh(tx, &sigs[i], &key); - } - /* Now broadcast the transaction */ withdraw->hextx = tal_hex(withdraw, linearize_tx(cmd, tx)); bitcoind_sendrawtx(cmd->ld->topology->bitcoind, withdraw->hextx,