diff --git a/bitcoin/signature.c b/bitcoin/signature.c index 362e53551..2b6c7c29f 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -88,30 +88,19 @@ void sign_hash(const struct privkey *privkey, } /* Only does SIGHASH_ALL */ -static void sha256_tx_one_input(struct bitcoin_tx *tx, +static void sha256_tx_one_input(const struct bitcoin_tx *tx, size_t input_num, const u8 *script, const u8 *witness_script, struct sha256_double *hash) { - size_t i; - assert(input_num < tal_count(tx->input)); - /* You must have all inputs zeroed to start. */ - for (i = 0; i < tal_count(tx->input); i++) - assert(!tx->input[i].script); - - tx->input[input_num].script = cast_const(u8 *, script); - - sha256_tx_for_sig(hash, tx, input_num, witness_script); - - /* Reset it for next time. */ - tx->input[input_num].script = NULL; + sha256_tx_for_sig(hash, tx, input_num, script, witness_script); } /* Only does SIGHASH_ALL */ -void sign_tx_input(struct bitcoin_tx *tx, +void sign_tx_input(const struct bitcoin_tx *tx, unsigned int in, const u8 *subscript, const u8 *witness_script, @@ -137,7 +126,7 @@ bool check_signed_hash(const struct sha256_double *hash, return ret == 1; } -bool check_tx_sig(struct bitcoin_tx *tx, size_t input_num, +bool check_tx_sig(const struct bitcoin_tx *tx, size_t input_num, const u8 *redeemscript, const u8 *witness_script, const struct pubkey *key, diff --git a/bitcoin/signature.h b/bitcoin/signature.h index c3608cc4e..cfa58ef49 100644 --- a/bitcoin/signature.h +++ b/bitcoin/signature.h @@ -26,8 +26,7 @@ bool check_signed_hash(const struct sha256_double *hash, const secp256k1_ecdsa_signature *signature, const struct pubkey *key); -/* All tx input scripts must be set to 0 len. */ -void sign_tx_input(struct bitcoin_tx *tx, +void sign_tx_input(const struct bitcoin_tx *tx, unsigned int in, const u8 *subscript, const u8 *witness, @@ -35,7 +34,7 @@ void sign_tx_input(struct bitcoin_tx *tx, secp256k1_ecdsa_signature *sig); /* Does this sig sign the tx with this input for this pubkey. */ -bool check_tx_sig(struct bitcoin_tx *tx, size_t input_num, +bool check_tx_sig(const struct bitcoin_tx *tx, size_t input_num, const u8 *redeemscript, const u8 *witness, const struct pubkey *key, diff --git a/bitcoin/tx.c b/bitcoin/tx.c index b0495b737..28bb82bfa 100644 --- a/bitcoin/tx.c +++ b/bitcoin/tx.c @@ -14,11 +14,12 @@ #define SEGREGATED_WITNESS_FLAG 0x1 static void push_tx_input(const struct bitcoin_tx_input *input, - void (*push)(const void *, size_t, void *), void *pushp) + const u8 *input_script, + void (*push)(const void *, size_t, void *), void *pushp) { push(&input->txid, sizeof(input->txid), pushp); push_le32(input->index, push, pushp); - push_varint_blob(input->script, push, pushp); + push_varint_blob(input_script, push, pushp); push_le32(input->sequence_number, push, pushp); } @@ -78,9 +79,15 @@ static void push_witnesses(const struct bitcoin_tx *tx, } } +/* For signing, we ignore input scripts on other inputs, and pretend + * the current input has a certain script: this is indicated by a + * non-NULL override_script, and setting override_script_index to the + * input number to replace. */ static void push_tx(const struct bitcoin_tx *tx, - void (*push)(const void *, size_t, void *), void *pushp, - bool bip144) + const u8 *override_script, + size_t override_script_index, + void (*push)(const void *, size_t, void *), void *pushp, + bool bip144) { varint_t i; u8 flag = 0; @@ -102,8 +109,16 @@ static void push_tx(const struct bitcoin_tx *tx, } push_varint(tal_count(tx->input), push, pushp); - for (i = 0; i < tal_count(tx->input); i++) - push_tx_input(&tx->input[i], push, pushp); + for (i = 0; i < tal_count(tx->input); i++) { + const u8 *input_script = tx->input[i].script; + if (override_script) { + if (override_script_index == i) + input_script = override_script; + else + input_script = NULL; + } + push_tx_input(&tx->input[i], input_script, push, pushp); + } push_varint(tal_count(tx->output), push, pushp); for (i = 0; i < tal_count(tx->output); i++) @@ -216,23 +231,19 @@ static void hash_for_segwit(struct sha256_ctx *ctx, void sha256_tx_for_sig(struct sha256_double *h, const struct bitcoin_tx *tx, unsigned int input_num, + const u8 *script, const u8 *witness_script) { - size_t i; struct sha256_ctx ctx = SHA256_INIT; - /* Caller should zero-out other scripts for signing! */ assert(input_num < tal_count(tx->input)); - for (i = 0; i < tal_count(tx->input); i++) - if (i != input_num) - assert(!tx->input[i].script); if (witness_script) { /* BIP143 hashing if OP_CHECKSIG is inside witness. */ hash_for_segwit(&ctx, tx, input_num, witness_script); } else { /* Otherwise signature hashing never includes witness. */ - push_tx(tx, push_sha, &ctx, false); + push_tx(tx, script, input_num, push_sha, &ctx, false); } sha256_le32(&ctx, SIGHASH_ALL); @@ -251,7 +262,7 @@ static void push_linearize(const void *data, size_t len, void *pptr_) u8 *linearize_tx(const tal_t *ctx, const struct bitcoin_tx *tx) { u8 *arr = tal_arr(ctx, u8, 0); - push_tx(tx, push_linearize, &arr, true); + push_tx(tx, NULL, 0, push_linearize, &arr, true); return arr; } @@ -263,7 +274,7 @@ static void push_measure(const void *data UNUSED, size_t len, void *lenp) size_t measure_tx_weight(const struct bitcoin_tx *tx) { size_t non_witness_len = 0, witness_len = 0; - push_tx(tx, push_measure, &non_witness_len, false); + push_tx(tx, NULL, 0, push_measure, &non_witness_len, false); if (uses_witness(tx)) { push_witnesses(tx, push_measure, &witness_len); /* Include BIP 144 marker and flag bytes in witness length */ @@ -279,7 +290,7 @@ void bitcoin_txid(const struct bitcoin_tx *tx, struct bitcoin_txid *txid) struct sha256_ctx ctx = SHA256_INIT; /* For TXID, we never use extended form. */ - push_tx(tx, push_sha, &ctx, false); + push_tx(tx, NULL, 0, push_sha, &ctx, false); sha256_double_done(&ctx, &txid->shad); } diff --git a/bitcoin/tx.h b/bitcoin/tx.h index 8c1813a27..28dd820bc 100644 --- a/bitcoin/tx.h +++ b/bitcoin/tx.h @@ -45,7 +45,9 @@ void bitcoin_txid(const struct bitcoin_tx *tx, struct bitcoin_txid *txid); /* Useful for signature code. */ void sha256_tx_for_sig(struct sha256_double *h, const struct bitcoin_tx *tx, - unsigned int input_num, const u8 *witness_script); + unsigned int input_num, + const u8 *script, + const u8 *witness_script); /* Linear bytes of tx. */ u8 *linearize_tx(const tal_t *ctx, const struct bitcoin_tx *tx);