Browse Source

signature: fix signatures for p2sh inputs.

The subscript in this case is the redeemscript, not the input script.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1 where-the-500-went
Rusty Russell 10 years ago
parent
commit
8516798645
  1. 18
      check-commit-sig.c
  2. 14
      open-commit-sig.c
  3. 7
      signature.c
  4. 2
      signature.h

18
check-commit-sig.c

@ -28,7 +28,7 @@ int main(int argc, char *argv[])
OpenCommitSig *cs2; OpenCommitSig *cs2;
struct bitcoin_tx *anchor, *commit; struct bitcoin_tx *anchor, *commit;
struct sha256_double txid; struct sha256_double txid;
u8 *tx_arr; u8 *tx_arr, *subscript;
size_t *inmap, *outmap; size_t *inmap, *outmap;
struct pubkey pubkey1, pubkey2; struct pubkey pubkey1, pubkey2;
struct bitcoin_signature sig1, sig2; struct bitcoin_signature sig1, sig2;
@ -58,6 +58,10 @@ int main(int argc, char *argv[])
if (!testnet) if (!testnet)
errx(1, "Private key '%s' not on testnet!", argv[4]); errx(1, "Private key '%s' not on testnet!", argv[4]);
/* Pubkey well-formed? */
if (!proto_to_pubkey(o2->anchor->pubkey, &pubkey2))
errx(1, "Invalid anchor-2 key");
/* Get the transaction ID of the anchor. */ /* Get the transaction ID of the anchor. */
anchor = anchor_tx_create(ctx, o1, o2, &inmap, &outmap); anchor = anchor_tx_create(ctx, o1, o2, &inmap, &outmap);
if (!anchor) if (!anchor)
@ -79,19 +83,17 @@ int main(int argc, char *argv[])
* is overkill: if their signature and pubkey signed the commit txin, * is overkill: if their signature and pubkey signed the commit txin,
* we're happy. */ * we're happy. */
sig1.stype = SIGHASH_ALL; sig1.stype = SIGHASH_ALL;
sign_tx_input(ctx, commit, 0, anchor->output[outmap[0]].script, subscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2);
anchor->output[outmap[0]].script_length, privkey, sign_tx_input(ctx, commit, 0, subscript, tal_count(subscript),
&sig1.sig); privkey, &sig1.sig);
/* Signatures and pubkeys well-formed? */ /* Signatures well-formed? */
if (!proto_to_signature(cs2->sig, &sig2.sig)) if (!proto_to_signature(cs2->sig, &sig2.sig))
errx(1, "Invalid commit-sig-2"); errx(1, "Invalid commit-sig-2");
sig2.stype = SIGHASH_ALL; sig2.stype = SIGHASH_ALL;
if (!proto_to_pubkey(o2->anchor->pubkey, &pubkey2))
errx(1, "Invalid anchor-2 key");
/* Combined signatures must validate correctly. */ /* Combined signatures must validate correctly. */
if (!check_2of2_sig(commit, 0, &anchor->output[outmap[0]], if (!check_2of2_sig(commit, 0, subscript, tal_count(subscript),
&pubkey1, &pubkey2, &sig1, &sig2)) &pubkey1, &pubkey2, &sig1, &sig2))
errx(1, "Signature failed"); errx(1, "Signature failed");

14
open-commit-sig.c

@ -32,7 +32,8 @@ int main(int argc, char *argv[])
size_t *inmap, *outmap; size_t *inmap, *outmap;
EC_KEY *privkey; EC_KEY *privkey;
bool testnet; bool testnet;
struct pubkey pubkey; struct pubkey pubkey1, pubkey2;
u8 *subscript;
err_set_progname(argv[0]); err_set_progname(argv[0]);
@ -49,7 +50,7 @@ int main(int argc, char *argv[])
o1 = pkt_from_file(argv[1], PKT__PKT_OPEN)->open; o1 = pkt_from_file(argv[1], PKT__PKT_OPEN)->open;
o2 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open; o2 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open;
privkey = key_from_base58(argv[3], strlen(argv[3]), &testnet, &pubkey); privkey = key_from_base58(argv[3], strlen(argv[3]), &testnet, &pubkey1);
if (!privkey) if (!privkey)
errx(1, "Invalid private key '%s'", argv[3]); errx(1, "Invalid private key '%s'", argv[3]);
if (!testnet) if (!testnet)
@ -74,9 +75,14 @@ int main(int argc, char *argv[])
(long long)o1->commitment_fee, (long long)o1->commitment_fee,
(long long)o2->commitment_fee); (long long)o2->commitment_fee);
/* Their pubkey must be valid */
if (!proto_to_pubkey(o2->anchor->pubkey, &pubkey2))
errx(1, "Invalid public open-channel-file2");
/* Sign it for them. */ /* Sign it for them. */
sign_tx_input(ctx, commit, 0, anchor->output[outmap[0]].script, subscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2);
anchor->output[outmap[0]].script_length, privkey, &sig); sign_tx_input(ctx, commit, 0, subscript, tal_count(subscript),
privkey, &sig);
pkt = open_commit_sig_pkt(ctx, &sig); pkt = open_commit_sig_pkt(ctx, &sig);
if (!write_all(STDOUT_FILENO, pkt, if (!write_all(STDOUT_FILENO, pkt,

7
signature.c

@ -137,7 +137,7 @@ out:
} }
bool check_2of2_sig(struct bitcoin_tx *tx, size_t input_num, bool check_2of2_sig(struct bitcoin_tx *tx, size_t input_num,
const struct bitcoin_tx_output *output, const u8 *redeemscript, size_t redeemscript_len,
const struct pubkey *key1, const struct pubkey *key2, const struct pubkey *key1, const struct pubkey *key2,
const struct bitcoin_signature *sig1, const struct bitcoin_signature *sig1,
const struct bitcoin_signature *sig2) const struct bitcoin_signature *sig2)
@ -145,9 +145,8 @@ bool check_2of2_sig(struct bitcoin_tx *tx, size_t input_num,
struct sha256_double hash; struct sha256_double hash;
assert(input_num < tx->input_count); assert(input_num < tx->input_count);
assert(is_p2sh(output->script, output->script_length)); sha256_tx_one_input(tx, input_num, redeemscript, redeemscript_len,
sha256_tx_one_input(tx, input_num, &hash);
output->script, output->script_length, &hash);
/* We only use SIGHASH_ALL for the moment. */ /* We only use SIGHASH_ALL for the moment. */
if (sig1->stype != SIGHASH_ALL || sig2->stype != SIGHASH_ALL) if (sig1->stype != SIGHASH_ALL || sig2->stype != SIGHASH_ALL)

2
signature.h

@ -35,7 +35,7 @@ bool sign_tx_input(const tal_t *ctx, struct bitcoin_tx *tx,
EC_KEY *privkey, struct signature *sig); EC_KEY *privkey, struct signature *sig);
bool check_2of2_sig(struct bitcoin_tx *tx, size_t input_num, bool check_2of2_sig(struct bitcoin_tx *tx, size_t input_num,
const struct bitcoin_tx_output *spending, const u8 *redeemscript, size_t redeemscript_len,
const struct pubkey *key1, const struct pubkey *key2, const struct pubkey *key1, const struct pubkey *key2,
const struct bitcoin_signature *sig1, const struct bitcoin_signature *sig1,
const struct bitcoin_signature *sig2); const struct bitcoin_signature *sig2);

Loading…
Cancel
Save