From ccff3ac43740b1242e9f7538ee1c7aaf898a5150 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 7 Mar 2017 11:31:55 +1030 Subject: [PATCH] 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 --- bitcoin/script.c | 12 ++++++++++++ bitcoin/script.h | 3 +++ lightningd/build_utxos.c | 17 ----------------- lightningd/build_utxos.h | 5 ----- lightningd/funding_tx.c | 12 +++++++++++- lightningd/funding_tx.h | 14 +++++++++++++- lightningd/gossip/Makefile | 2 +- lightningd/handshake/Makefile | 2 +- lightningd/handshake/test/Makefile | 2 +- lightningd/hsm/hsm.c | 3 ++- lightningd/key_derive.c | 20 ++++++++++++++++++++ lightningd/key_derive.h | 4 ++++ lightningd/opening/Makefile | 2 +- lightningd/peer_control.c | 5 +++-- lightningd/test/Makefile | 2 +- lightningd/test/run-funding_tx.c | 5 ++++- 16 files changed, 77 insertions(+), 33 deletions(-) diff --git a/bitcoin/script.c b/bitcoin/script.c index 1b606f107..d45d1e8cf 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -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, diff --git a/bitcoin/script.h b/bitcoin/script.h index b6ceb79c1..6f10be179 100644 --- a/bitcoin/script.h +++ b/bitcoin/script.h @@ -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); diff --git a/lightningd/build_utxos.c b/lightningd/build_utxos.c index 9223852ae..a737e1175 100644 --- a/lightningd/build_utxos.c +++ b/lightningd/build_utxos.c @@ -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; -} - diff --git a/lightningd/build_utxos.h b/lightningd/build_utxos.h index b00344b49..9fa0fde91 100644 --- a/lightningd/build_utxos.h +++ b/lightningd/build_utxos.h @@ -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 */ diff --git a/lightningd/funding_tx.c b/lightningd/funding_tx.c index e9d51194d..b3a12ce97 100644 --- a/lightningd/funding_tx.c +++ b/lightningd/funding_tx.c @@ -1,8 +1,10 @@ #include "funding_tx.h" #include +#include #include #include #include +#include #include #include @@ -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; diff --git a/lightningd/funding_tx.h b/lightningd/funding_tx.h index acf6f60ea..5784d333a 100644 --- a/lightningd/funding_tx.h +++ b/lightningd/funding_tx.h @@ -5,6 +5,7 @@ #include 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 */ diff --git a/lightningd/gossip/Makefile b/lightningd/gossip/Makefile index ab19c656a..b2a5d20a1 100644 --- a/lightningd/gossip/Makefile +++ b/lightningd/gossip/Makefile @@ -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 diff --git a/lightningd/handshake/Makefile b/lightningd/handshake/Makefile index ee586910b..3a4cff2e2 100644 --- a/lightningd/handshake/Makefile +++ b/lightningd/handshake/Makefile @@ -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/%) diff --git a/lightningd/handshake/test/Makefile b/lightningd/handshake/test/Makefile index 4e110267f..80f63f011 100644 --- a/lightningd/handshake/test/Makefile +++ b/lightningd/handshake/test/Makefile @@ -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) diff --git a/lightningd/hsm/hsm.c b/lightningd/hsm/hsm.c index 6c30b0b35..32fc182ca 100644 --- a/lightningd/hsm/hsm.c +++ b/lightningd/hsm/hsm.c @@ -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)); diff --git a/lightningd/key_derive.c b/lightningd/key_derive.c index 808792a0f..f5aee1538 100644 --- a/lightningd/key_derive.c +++ b/lightningd/key_derive.c @@ -3,6 +3,7 @@ #include #include #include +#include /* 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; +} diff --git a/lightningd/key_derive.h b/lightningd/key_derive.h index 13e1a7030..a46a5bde1 100644 --- a/lightningd/key_derive.h +++ b/lightningd/key_derive.h @@ -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 */ diff --git a/lightningd/opening/Makefile b/lightningd/opening/Makefile index a93ccebe0..bf25cabef 100644 --- a/lightningd/opening/Makefile +++ b/lightningd/opening/Makefile @@ -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/%) diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index aeee6ab2f..1642f35ac 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -18,12 +18,12 @@ #include #include #include +#include #include #include #include #include #include -#include #include 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); diff --git a/lightningd/test/Makefile b/lightningd/test/Makefile index 707fc390e..00c4a1efb 100644 --- a/lightningd/test/Makefile +++ b/lightningd/test/Makefile @@ -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) diff --git a/lightningd/test/run-funding_tx.c b/lightningd/test/run-funding_tx.c index 6a059a535..b883f2887 100644 --- a/lightningd/test/run-funding_tx.c +++ b/lightningd/test/run-funding_tx.c @@ -8,6 +8,8 @@ #include #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);