Browse Source

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 <rusty@rustcorp.com.au>
plugin-6
Rusty Russell 6 years ago
committed by Christian Decker
parent
commit
a83e45fec2
  1. 19
      bitcoin/signature.c
  2. 5
      bitcoin/signature.h
  3. 41
      bitcoin/tx.c
  4. 4
      bitcoin/tx.h

19
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,

5
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,

41
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);
}

4
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);

Loading…
Cancel
Save