diff --git a/lightningd/funding_tx.c b/lightningd/funding_tx.c index 0d33b2536..43b23cb21 100644 --- a/lightningd/funding_tx.c +++ b/lightningd/funding_tx.c @@ -2,6 +2,8 @@ #include #include #include +#include +#include #include #ifndef SUPERVERBOSE @@ -9,9 +11,8 @@ #endif struct bitcoin_tx *funding_tx(const tal_t *ctx, - const struct sha256_double *input_txid, - unsigned int input_txout, - u64 input_satoshis, + u32 *outnum, + const struct utxo *utxos, u64 funding_satoshis, const struct pubkey *local_fundingkey, const struct pubkey *remote_fundingkey, @@ -19,13 +20,17 @@ struct bitcoin_tx *funding_tx(const tal_t *ctx, u64 feerate_per_kw, u64 dust_limit_satoshis) { - struct bitcoin_tx *tx = bitcoin_tx(ctx, 1, 2); + struct bitcoin_tx *tx = bitcoin_tx(ctx, tal_count(utxos), 2); u8 *wscript; - u64 fee, weight; + u64 fee, weight, input_satoshis = 0; + size_t i; - tx->input[0].txid = *input_txid; - tx->input[0].index = input_txout; - tx->input[0].amount = tal_dup(tx, u64, &input_satoshis); + for (i = 0; i < tal_count(utxos); i++) { + tx->input[i].txid = utxos[i].txid; + tx->input[i].index = utxos[i].outnum; + tx->input[i].amount = tal_dup(tx, u64, &utxos[i].amount); + input_satoshis += utxos[i].amount; + } tx->output[0].amount = funding_satoshis; wscript = bitcoin_redeem_2of2(tx, local_fundingkey, remote_fundingkey); @@ -42,26 +47,17 @@ struct bitcoin_tx *funding_tx(const tal_t *ctx, fee = weight * feerate_per_kw / 1000; /* Too small an output after fee? Drop it. */ - if (input_satoshis - funding_satoshis < dust_limit_satoshis + fee) + if (input_satoshis - funding_satoshis < dust_limit_satoshis + fee) { tal_resize(&tx->output, 1); - else { + *outnum = 0; + } else { + const void *map[2]; + map[0] = int2ptr(0); + map[1] = int2ptr(1); tx->output[1].amount = input_satoshis - funding_satoshis - fee; - permute_outputs(tx->output, tal_count(tx->output), NULL); + permute_outputs(tx->output, tal_count(tx->output), map); + *outnum = (map[0] == int2ptr(0) ? 0 : 1); } return tx; } - -void sign_funding_tx(struct bitcoin_tx *funding, - const struct pubkey *inputkey, - const struct privkey *input_privkey) -{ - secp256k1_ecdsa_signature sig; - u8 *subscript = scriptpubkey_p2pkh(funding, inputkey); - - sign_tx_input(funding, 0, subscript, NULL, input_privkey, inputkey, - &sig); - tal_free(subscript); - - funding->input[0].script = bitcoin_redeem_p2pkh(funding, inputkey, &sig); -} diff --git a/lightningd/funding_tx.h b/lightningd/funding_tx.h index ec65275b2..e2c6bb2e3 100644 --- a/lightningd/funding_tx.h +++ b/lightningd/funding_tx.h @@ -8,22 +8,27 @@ struct bitcoin_tx; struct privkey; struct pubkey; struct sha256_double; +struct utxo; -/* Create funding tx which spends a single P2PKH input, produces a - * P2WPKH change output (if over dust limit). */ +/** + * funding_tx: create a P2WSH funding transaction for a channel. + * @ctx: context to tal from. + * @outnum: txout (0 or 1) which is the funding output. + * @utxo: tal_arr of UTXO to spend as inputs. + * @funding_satoshis: satoshis to output. + * @local_fundingkey: local key for 2of2 funding output. + * @remote_fundingkey: remote key for 2of2 funding output. + * @changekey: key to send change to (if any). + * @feerate_per_kw: feerate for transaction. + * @dust_limit_satoshis: dust limit to trim change output by. + */ struct bitcoin_tx *funding_tx(const tal_t *ctx, - const struct sha256_double *input_txid, - unsigned int input_txout, - u64 input_satoshis, + u32 *outnum, + const struct utxo *utxos, u64 funding_satoshis, const struct pubkey *local_fundingkey, const struct pubkey *remote_fundingkey, const struct pubkey *changekey, u64 feerate_per_kw, u64 dust_limit_satoshis); - -void sign_funding_tx(struct bitcoin_tx *funding, - const struct pubkey *inputkey, - const struct privkey *input_privkey); - #endif /* LIGHTNING_LIGHTNINGD_FUNDING_TX_H */ diff --git a/lightningd/test/run-funding_tx.c b/lightningd/test/run-funding_tx.c index 00db3b050..1dd78578c 100644 --- a/lightningd/test/run-funding_tx.c +++ b/lightningd/test/run-funding_tx.c @@ -39,16 +39,16 @@ int main(void) { tal_t *tmpctx = tal_tmpctx(NULL); struct bitcoin_tx *input, *funding; - struct sha256_double txid; u64 feerate_per_kw; struct pubkey local_funding_pubkey, remote_funding_pubkey; struct privkey input_privkey; struct pubkey inputkey; bool testnet; - unsigned int input_txout; - u64 input_satoshis; + struct utxo *utxo = tal_arr(tmpctx, struct utxo, 1); u64 funding_satoshis; - int funding_outnum; + u32 funding_outnum; + u8 *subscript; + secp256k1_ecdsa_signature sig; secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN); @@ -89,32 +89,37 @@ int main(void) &remote_funding_pubkey)) abort(); - bitcoin_txid(input, &txid); - input_txout = 0; - input_satoshis = 5000000000; + bitcoin_txid(input, &utxo->txid); + utxo->outnum = 0; + utxo->amount = 5000000000; funding_satoshis = 10000000; feerate_per_kw = 15000; - printf("input[0] txid: %s\n", tal_hexstr(tmpctx, &txid, sizeof(txid))); - printf("input[0] input: %u\n", input_txout); - printf("input[0] satoshis: %"PRIu64"\n", input_satoshis); + printf("input[0] txid: %s\n", + tal_hexstr(tmpctx, &utxo->txid, sizeof(utxo->txid))); + printf("input[0] input: %u\n", utxo->outnum); + printf("input[0] satoshis: %"PRIu64"\n", utxo->amount); printf("funding satoshis: %"PRIu64"\n", funding_satoshis); - funding = funding_tx(tmpctx, &txid, input_txout, input_satoshis, + funding = funding_tx(tmpctx, &funding_outnum, utxo, funding_satoshis, &local_funding_pubkey, &remote_funding_pubkey, &inputkey, feerate_per_kw, 0); - funding_outnum = (funding->output[0].amount == funding_satoshis ? 0 : 1); printf("# feerate_per_kw: %"PRIu64"\n", feerate_per_kw); printf("change satoshis: %"PRIu64"\n", funding->output[!funding_outnum].amount); printf("funding output: %u\n", funding_outnum); - sign_funding_tx(funding, &inputkey, &input_privkey); + subscript = scriptpubkey_p2pkh(funding, &inputkey); + sign_tx_input(funding, 0, subscript, NULL, &input_privkey, &inputkey, + &sig); + + funding->input[0].script = bitcoin_redeem_p2pkh(funding, &inputkey, + &sig); printf("funding tx: %s\n", tal_hex(tmpctx, linearize_tx(tmpctx, funding)));