From bd0b762b2fe0410d0e36108292ccf2bf117eb09a Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 20 Dec 2017 06:04:00 +1030 Subject: [PATCH] hsm: fix complex withdrawl transactions. Firstly, not every output is a P2SH (our change outputs aren't, and in future we'll have native incoming segwit txs). Secondly, withdraw_tx() permutes the utxo array, so we can't use a temporary: we got away with it because we were always using the same key! Signed-off-by: Rusty Russell --- hsmd/hsm.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/hsmd/hsm.c b/hsmd/hsm.c index e0eba7529..7e68ba6ee 100644 --- a/hsmd/hsm.c +++ b/hsmd/hsm.c @@ -599,7 +599,8 @@ static void sign_withdrawal_tx(struct daemon_conn *master, const u8 *msg) const tal_t *tmpctx = tal_tmpctx(master); u64 satoshi_out, change_out; u32 change_keyindex; - struct utxo *utxos; + struct utxo *inutxos; + const struct utxo **utxos; secp256k1_ecdsa_signature *sigs; u8 *wscript; struct bitcoin_tx *tx; @@ -609,7 +610,7 @@ static void sign_withdrawal_tx(struct daemon_conn *master, const u8 *msg) if (!fromwire_hsm_sign_withdrawal(tmpctx, msg, NULL, &satoshi_out, &change_out, &change_keyindex, - &scriptpubkey, &utxos)) { + &scriptpubkey, &inutxos)) { status_trace("Failed to parse sign_withdrawal: %s", tal_hex(trc, msg)); return; @@ -622,9 +623,11 @@ static void sign_withdrawal_tx(struct daemon_conn *master, const u8 *msg) return; } + /* We need an array of pointers, since withdraw_tx permutes them */ + utxos = to_utxoptr_arr(tmpctx, inutxos); pubkey_from_der(ext.pub_key, sizeof(ext.pub_key), &changekey); tx = withdraw_tx( - tmpctx, to_utxoptr_arr(tmpctx, utxos), scriptpubkey, satoshi_out, + tmpctx, utxos, scriptpubkey, satoshi_out, &changekey, change_out, NULL); /* Now generate signatures. */ @@ -632,12 +635,14 @@ static void sign_withdrawal_tx(struct daemon_conn *master, const u8 *msg) for (size_t i = 0; i < tal_count(utxos); i++) { struct pubkey inkey; struct privkey inprivkey; - const struct utxo *in = &utxos[i]; + const struct utxo *in = utxos[i]; u8 *subscript; bitcoin_keypair(&inprivkey, &inkey, in->keyindex); - /* We know these are p2sh since that's the only kind we handle */ - subscript = bitcoin_redeem_p2sh_p2wpkh(tmpctx, &inkey); + if (utxos[i]->is_p2sh) + subscript = bitcoin_redeem_p2sh_p2wpkh(tmpctx, &inkey); + else + subscript = NULL; wscript = p2wpkh_scriptcode(tmpctx, &inkey); sign_tx_input(tx, i, subscript, wscript,