From a83e45fec2967745cbde2f875393dc231f1b1643 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 3 Dec 2018 09:37:06 +1030 Subject: [PATCH] bitcoin/signature: create/check tx sigs without mangling the tx. We currently make sure that all the bitcoin_tx input scripts are NULL and set the input script of the input we're signing, so we can easily reuse the tx hashing code for signature checks. This means that we sometimes jump through hoops to make sure input scripts are NULL, and also means that the tx can't be const. Put more logic inside bitcoin/tx so it can simply ignore things we don't want to hash. Signed-off-by: Rusty Russell --- bitcoin/signature.c | 19 ++++--------------- bitcoin/signature.h | 5 ++--- bitcoin/tx.c | 41 ++++++++++++++++++++++++++--------------- bitcoin/tx.h | 4 +++- 4 files changed, 35 insertions(+), 34 deletions(-) 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);