lightningd/funding_tx: fill in scriptsigs for p2sh UTXOs.

This is a bit tricky: for our signing code, we don't want scriptsigs,
but to calculate the txid, we need them.  For most transactions in lightning,
they're pure segwit so it doesn't matter, but funding transactions can
have P2SH-wrapped P2WPKH inputs.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2017-03-07 11:31:55 +10:30
parent afc31cd68f
commit ccff3ac437
16 changed files with 77 additions and 33 deletions

View File

@ -259,6 +259,18 @@ u8 *bitcoin_redeem_p2wpkh(const tal_t *ctx, const struct pubkey *key)
return script;
}
u8 *bitcoin_scriptsig_p2sh_p2wpkh(const tal_t *ctx, const struct pubkey *key)
{
u8 *redeemscript = bitcoin_redeem_p2wpkh(ctx, key), *script;
/* BIP141: The scriptSig must be exactly a push of the BIP16
* redeemScript or validation fails. */
script = tal_arr(ctx, u8, 0);
add_push_bytes(&script, redeemscript, tal_count(redeemscript));
tal_free(redeemscript);
return script;
}
/* Create an input which spends the p2sh-p2wpkh. */
void bitcoin_witness_p2sh_p2wpkh(const tal_t *ctx,
struct bitcoin_tx_input *input,

View File

@ -51,6 +51,9 @@ void bitcoin_witness_p2sh_p2wpkh(const tal_t *ctx,
const secp256k1_ecdsa_signature *sig,
const struct pubkey *key);
/* Create scriptsig for p2sh-p2wpkh */
u8 *bitcoin_scriptsig_p2sh_p2wpkh(const tal_t *ctx, const struct pubkey *key);
/* Create scriptcode (fake witness, basically) for P2WPKH */
u8 *p2wpkh_scriptcode(const tal_t *ctx, const struct pubkey *key);

View File

@ -246,20 +246,3 @@ const struct utxo **build_utxos(const tal_t *ctx,
return tal_free(utxos);
}
bool bip32_pubkey(const struct ext_key *bip32_base,
struct pubkey *pubkey, u32 index)
{
struct ext_key ext;
assert(index < BIP32_INITIAL_HARDENED_CHILD);
if (bip32_key_from_parent(bip32_base, index,
BIP32_FLAG_KEY_PUBLIC, &ext) != WALLY_OK)
return false;
if (!secp256k1_ec_pubkey_parse(secp256k1_ctx, &pubkey->pubkey,
ext.pub_key, sizeof(ext.pub_key)))
return false;
return true;
}

View File

@ -13,9 +13,4 @@ const struct utxo **build_utxos(const tal_t *ctx,
/* Once we've spent them, mark them confirmed. */
void confirm_utxos(struct lightningd *ld, const struct utxo **utxos);
struct ext_key;
bool bip32_pubkey(const struct ext_key *bip32_base,
struct pubkey *pubkey, u32 index);
#endif /* LIGHTNING_LIGHTNINGD_BUILD_UTXOS_H */

View File

@ -1,8 +1,10 @@
#include "funding_tx.h"
#include <assert.h>
#include <bitcoin/pubkey.h>
#include <bitcoin/script.h>
#include <bitcoin/tx.h>
#include <ccan/ptrint/ptrint.h>
#include <lightningd/key_derive.h>
#include <lightningd/utxo.h>
#include <permute_tx.h>
@ -17,7 +19,8 @@ struct bitcoin_tx *funding_tx(const tal_t *ctx,
const struct pubkey *local_fundingkey,
const struct pubkey *remote_fundingkey,
u64 change_satoshis,
const struct pubkey *changekey)
const struct pubkey *changekey,
const struct ext_key *bip32_base)
{
struct bitcoin_tx *tx = bitcoin_tx(ctx, tal_count(utxomap),
change_satoshis ? 2 : 1);
@ -28,6 +31,13 @@ struct bitcoin_tx *funding_tx(const tal_t *ctx,
tx->input[i].txid = utxomap[i]->txid;
tx->input[i].index = utxomap[i]->outnum;
tx->input[i].amount = tal_dup(tx, u64, &utxomap[i]->amount);
if (utxomap[i]->is_p2sh && bip32_base) {
struct pubkey key;
bip32_pubkey(bip32_base, &key, utxomap[i]->keyindex);
tx->input[i].script
= bitcoin_scriptsig_p2sh_p2wpkh(tx, &key);
}
}
tx->output[0].amount = funding_satoshis;

View File

@ -5,6 +5,7 @@
#include <ccan/tal/tal.h>
struct bitcoin_tx;
struct ext_key;
struct privkey;
struct pubkey;
struct sha256_double;
@ -20,6 +21,16 @@ struct utxo;
* @remote_fundingkey: (in) remote key for 2of2 funding output.
* @change_satoshis: (in) amount to send as change.
* @changekey: (in) key to send change to (only used if change_satoshis != 0).
* @bip32_base: (in) bip32 base for key derivation, or NULL.
*
* If bip32_base is supplied, scriptSig will be added for p2sh inputs: this
* means our signing code will fail, but txid will be correct. If NULL,
* the txid will be incorrect, by signing will succeed.
*
* This is done because all other txs have no scriptSig (being pure Segwit)
* so our signature code simply asserts there's no scriptsig (which would
* have to be removed for signing anyway). The funding transaction is
* a special case because of the P2SH inputs.
*/
struct bitcoin_tx *funding_tx(const tal_t *ctx,
u32 *outnum,
@ -28,5 +39,6 @@ struct bitcoin_tx *funding_tx(const tal_t *ctx,
const struct pubkey *local_fundingkey,
const struct pubkey *remote_fundingkey,
u64 change_satoshis,
const struct pubkey *changekey);
const struct pubkey *changekey,
const struct ext_key *bip32_base);
#endif /* LIGHTNING_LIGHTNINGD_FUNDING_TX_H */

View File

@ -39,7 +39,7 @@ $(LIGHTNINGD_GOSSIP_CONTROL_OBJS) : $(LIGHTNINGD_GOSSIP_CONTROL_HEADERS)
lightningd/gossip-all: lightningd/lightningd_gossip $(LIGHTNINGD_GOSSIP_CLIENT_OBJS)
lightningd/lightningd_gossip: $(LIGHTNINGD_GOSSIP_OBJS) $(CORE_OBJS) $(CORE_TX_OBJS) $(BITCOIN_OBJS) $(WIRE_OBJS) $(CCAN_OBJS) $(LIGHTNINGD_OLD_LIB_OBJS) $(LIGHTNINGD_LIB_OBJS) $(LIBBASE58_OBJS) libsecp256k1.a libsodium.a
lightningd/lightningd_gossip: $(LIGHTNINGD_GOSSIP_OBJS) $(CORE_OBJS) $(CORE_TX_OBJS) $(BITCOIN_OBJS) $(WIRE_OBJS) $(CCAN_OBJS) $(LIGHTNINGD_OLD_LIB_OBJS) $(LIGHTNINGD_LIB_OBJS) $(LIBBASE58_OBJS) libsecp256k1.a libsodium.a libwallycore.a
$(CC) $(CFLAGS) -o $@ $^ $(LDLIBS)
lightningd/gossip/gen_gossip_control_wire.h: $(WIRE_GEN) lightningd/gossip/gossip_control_wire_csv

View File

@ -44,7 +44,7 @@ lightningd/handshake/gen_handshake_status_wire.c: $(WIRE_GEN) lightningd/handsha
LIGHTNINGD_HANDSHAKE_OBJS := $(LIGHTNINGD_HANDSHAKE_SRC:.c=.o) $(LIGHTNINGD_HANDSHAKE_GEN_SRC:.c=.o)
lightningd/lightningd_handshake: $(LIGHTNINGD_OLD_LIB_OBJS) $(LIGHTNINGD_LIB_OBJS) $(LIGHTNINGD_HANDSHAKE_OBJS) $(CORE_OBJS) $(CORE_TX_OBJS) $(WIRE_OBJS) $(BITCOIN_OBJS) $(CCAN_OBJS) $(LIGHTNINGD_HSM_CLIENT_OBJS) $(LIBBASE58_OBJS) libsecp256k1.a libsodium.a
lightningd/lightningd_handshake: $(LIGHTNINGD_OLD_LIB_OBJS) $(LIGHTNINGD_LIB_OBJS) $(LIGHTNINGD_HANDSHAKE_OBJS) $(CORE_OBJS) $(CORE_TX_OBJS) $(WIRE_OBJS) $(BITCOIN_OBJS) $(CCAN_OBJS) $(LIGHTNINGD_HSM_CLIENT_OBJS) $(LIBBASE58_OBJS) libsecp256k1.a libsodium.a libwallycore.a
$(CC) $(CFLAGS) -o $@ $^ $(LDLIBS)
check-source: $(LIGHTNINGD_HANDSHAKE_SRC_NOGEN:%=check-src-include-order/%)

View File

@ -8,7 +8,7 @@ LIGHTNINGD_HANDSHAKE_TEST_PROGRAMS := $(LIGHTNINGD_HANDSHAKE_TEST_OBJS:.o=)
update-mocks: $(LIGHTNINGD_HANDSHAKE_TEST_SRC:%=update-mocks/%)
$(LIGHTNINGD_HANDSHAKE_TEST_PROGRAMS): $(CCAN_OBJS) $(BITCOIN_OBJS) $(CORE_TX_OBJS) $(CORE_OBJS) $(WIRE_OBJS) $(LIBBASE58_OBJS) $(LIGHTNINGD_LIB_OBJS) $(LIGHTNINGD_OLD_LIB_OBJS) libsecp256k1.a libsodium.a utils.o $(LIGHTNINGD_HANDSHAKE_GEN_SRC:.c=.o)
$(LIGHTNINGD_HANDSHAKE_TEST_PROGRAMS): $(CCAN_OBJS) $(BITCOIN_OBJS) $(CORE_TX_OBJS) $(CORE_OBJS) $(WIRE_OBJS) $(LIBBASE58_OBJS) $(LIGHTNINGD_LIB_OBJS) $(LIGHTNINGD_OLD_LIB_OBJS) libsecp256k1.a libsodium.a utils.o $(LIGHTNINGD_HANDSHAKE_GEN_SRC:.c=.o) libwallycore.a
$(LIGHTNINGD_HANDSHAKE_TEST_OBJS): $(LIGHTNINGD_HANDSHAKE_HEADERS) $(LIGHTNINGD_LIB_HEADERS) $(BITCOIN_HEADERS) $(CORE_HEADERS) $(GEN_HEADERS) $(WIRE_HEADERS) $(CCAN_HEADERS) $(LIBBASE58_HEADERS) $(LIBSODIUM_HEADERS)

View File

@ -386,7 +386,8 @@ static u8 *sign_funding_tx(const tal_t *ctx, const u8 *data)
tx = funding_tx(tmpctx, &outnum, utxomap,
satoshi_out, &local_pubkey, &remote_pubkey,
change_out, &changekey);
change_out, &changekey,
NULL);
/* Now generate signatures. */
sig = tal_arr(tmpctx, secp256k1_ecdsa_signature, tal_count(inputs));

View File

@ -3,6 +3,7 @@
#include <ccan/crypto/sha256/sha256.h>
#include <lightningd/key_derive.h>
#include <utils.h>
#include <wally_bip32.h>
/* BOLT #3:
*
@ -236,3 +237,22 @@ bool derive_revocation_privkey(const struct privkey *base_secret,
#endif
return true;
}
bool bip32_pubkey(const struct ext_key *bip32_base,
struct pubkey *pubkey, u32 index)
{
struct ext_key ext;
if (index >= BIP32_INITIAL_HARDENED_CHILD)
return false;
if (bip32_key_from_parent(bip32_base, index,
BIP32_FLAG_KEY_PUBLIC, &ext) != WALLY_OK)
return false;
if (!secp256k1_ec_pubkey_parse(secp256k1_ctx, &pubkey->pubkey,
ext.pub_key, sizeof(ext.pub_key)))
return false;
return true;
}

View File

@ -25,4 +25,8 @@ bool derive_revocation_privkey(const struct privkey *base_secret,
const struct pubkey *per_commitment_point,
struct privkey *key);
struct ext_key;
bool bip32_pubkey(const struct ext_key *bip32_base,
struct pubkey *pubkey, u32 index);
#endif /* LIGHTNING_LIGHTNINGD_KEY_DERIVE_H */

View File

@ -50,7 +50,7 @@ lightningd/opening/gen_opening_status_wire.c: $(WIRE_GEN) lightningd/opening/ope
LIGHTNINGD_OPENING_OBJS := $(LIGHTNINGD_OPENING_SRC:.c=.o) $(LIGHTNINGD_OPENING_GEN_SRC:.c=.o)
lightningd/lightningd_opening: $(LIGHTNINGD_OLD_LIB_OBJS) $(LIGHTNINGD_LIB_OBJS) $(LIGHTNINGD_OPENING_OBJS) $(CORE_OBJS) $(CORE_TX_OBJS) $(WIRE_OBJS) $(BITCOIN_OBJS) $(CCAN_OBJS) $(LIGHTNINGD_HSM_CLIENT_OBJS) $(LIBBASE58_OBJS) libsecp256k1.a libsodium.a
lightningd/lightningd_opening: $(LIGHTNINGD_OLD_LIB_OBJS) $(LIGHTNINGD_LIB_OBJS) $(LIGHTNINGD_OPENING_OBJS) $(CORE_OBJS) $(CORE_TX_OBJS) $(WIRE_OBJS) $(BITCOIN_OBJS) $(CCAN_OBJS) $(LIGHTNINGD_HSM_CLIENT_OBJS) $(LIBBASE58_OBJS) libsecp256k1.a libsodium.a libwallycore.a
$(CC) $(CFLAGS) -o $@ $^ $(LDLIBS)
check-source: $(LIGHTNINGD_OPENING_SRC_NOGEN:%=check-src-include-order/%)

View File

@ -18,12 +18,12 @@
#include <lightningd/handshake/gen_handshake_control_wire.h>
#include <lightningd/handshake/gen_handshake_status_wire.h>
#include <lightningd/hsm/gen_hsm_control_wire.h>
#include <lightningd/key_derive.h>
#include <lightningd/opening/gen_opening_control_wire.h>
#include <lightningd/opening/gen_opening_status_wire.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <wally_bip32.h>
#include <wire/gen_peer_wire.h>
static void destroy_peer(struct peer *peer)
@ -583,7 +583,8 @@ static void opening_gen_funding(struct subdaemon *opening, const u8 *resp,
fc->funding_tx = funding_tx(fc, &outnum, fc->utxomap, fc->satoshi,
&fc->local_fundingkey,
&fc->remote_fundingkey,
fc->change, &changekey);
fc->change, &changekey,
fc->peer->ld->bip32_base);
bitcoin_txid(fc->funding_tx, &txid);
msg = towire_opening_open_funding(fc, &txid, outnum);

View File

@ -8,7 +8,7 @@ LIGHTNINGD_TEST_PROGRAMS := $(LIGHTNINGD_TEST_OBJS:.o=)
update-mocks: $(LIGHTNINGD_TEST_SRC:%=update-mocks/%)
$(LIGHTNINGD_TEST_PROGRAMS): $(CCAN_OBJS) $(CORE_OBJS) $(CORE_TX_OBJS) $(BITCOIN_OBJS) $(WIRE_OBJS) $(LIBBASE58_OBJS) $(LIGHTNINGD_OLD_LIB_OBJS) utils.o libsecp256k1.a libsodium.a
$(LIGHTNINGD_TEST_PROGRAMS): $(CCAN_OBJS) $(CORE_OBJS) $(CORE_TX_OBJS) $(BITCOIN_OBJS) $(WIRE_OBJS) $(LIBBASE58_OBJS) $(LIGHTNINGD_OLD_LIB_OBJS) utils.o libsecp256k1.a libsodium.a libwallycore.a
$(LIGHTNINGD_TEST_OBJS): $(LIGHTNINGD_HEADERS) $(LIGHTNINGD_SRC) $(LIGHTNINGD_LIB_SRC)

View File

@ -8,6 +8,8 @@
#include <utils.h>
#define SUPERVERBOSE printf
#include "../funding_tx.c"
#undef SUPERVERBOSE
#include "../key_derive.c"
#if 0
static struct sha256 sha256_from_hex(const char *hex)
@ -93,6 +95,7 @@ int main(void)
bitcoin_txid(input, &utxo.txid);
utxo.outnum = 0;
utxo.amount = 5000000000;
utxo.is_p2sh = false;
funding_satoshis = 10000000;
fee = 13920;
@ -108,7 +111,7 @@ int main(void)
&local_funding_pubkey,
&remote_funding_pubkey,
utxo.amount - fee - funding_satoshis,
&inputkey);
&inputkey, NULL);
printf("# fee: %"PRIu64"\n", fee);
printf("change satoshis: %"PRIu64"\n",
funding->output[!funding_outnum].amount);