Permalink
Browse files

fix Tx#signature_hash_for_input for SIGHASH_SINGLE edge case

  https://bitcointalk.org/index.php?topic=260595.0

  "
    I also forked webbtc.com on mainnet today with transaction 315ac7d4c26d69668129cc352851d9389b4a6868f1509c6c8b66bead11e2619f It has two inputs, both using SIGHHASH_SINGLE, and only one output. SignatureHash() in script.cpp has the following code:

    if (nOut >= txTmp.vout.size())
    {
      printf("ERROR: SignatureHash() : nOut=%d out of range\n", nOut);
      return 1;
    }

    The thing is, that's not actually an error. SignatureHash() returns the hash of the signature, and CheckSig() doesn't check the return code, so it acts as though the hash the signature signed was 0000000000000000000000000000000000000000000000000000000000000001 You can create a signature for that, and it works just fine and the transaction is considered valid.
  "
  • Loading branch information...
lian committed Jul 25, 2013
1 parent bc076e3 commit 4b8598b84367f9c53e4e6a7a5459a124c1165c7e
@@ -151,6 +151,8 @@ def signature_hash_for_input(input_idx, outpoint_tx, script_pubkey=nil, hash_typ
# https://github.com/bitcoin/bitcoin/blob/c2e8c8acd8ae0c94c70b59f55169841ad195bb99/src/script.cpp#L1058
# https://en.bitcoin.it/wiki/OP_CHECKSIG
return "\x01".ljust(32, "\x00") if input_idx >= @in.size # ERROR: SignatureHash() : input_idx=%d out of range
hash_type ||= SIGHASH_TYPE[:all]
pin = @in.map.with_index{|input,idx|
@@ -177,6 +179,7 @@ def signature_hash_for_input(input_idx, outpoint_tx, script_pubkey=nil, hash_typ
pout = ""
out_size = Protocol.pack_var_int(0)
when SIGHASH_TYPE[:single]
return "\x01".ljust(32, "\x00") if input_idx >= @out.size # ERROR: SignatureHash() : input_idx=%d out of range (SIGHASH_SINGLE)
pout = @out[0...(input_idx+1)].map.with_index{|out,idx| (idx==input_idx) ? out.to_payload : out.to_null_payload }.join
out_size = Protocol.pack_var_int(input_idx+1)
end
@@ -0,0 +1,31 @@
{
"hash":"315ac7d4c26d69668129cc352851d9389b4a6868f1509c6c8b66bead11e2619f",
"ver":1,
"confirmations":420,
"vin_sz":2,
"vout_sz":1,
"lock_time":0,
"size":339,
"in":[
{
"prev_out":{
"hash":"69216b8aaa35b76d6613e5f527f4858640d986e1046238583bdad79b35e938dc",
"n":0
},
"scriptSig":"304402205d8feeb312478e468d0b514e63e113958d7214fa572acd87079a7f0cc026fc5c02200fa76ea05bf243af6d0f9177f241caf606d01fcfd5e62d6befbca24e569e5c2703 02100a1a9ca2c18932d6577c58f225580184d0e08226d41959874ac963e3c1b2fe"
},
{
"prev_out":{
"hash":"69216b8aaa35b76d6613e5f527f4858640d986e1046238583bdad79b35e938dc",
"n":1
},
"scriptSig":"30450220087ede38729e6d35e4f515505018e659222031273b7366920f393ee3ab17bc1e022100ca43164b757d1a6d1235f13200d4b5f76dd8fda4ec9fc28546b2df5b1211e8df03 0275983913e60093b767e85597ca9397fb2f418e57f998d6afbbc536116085b1cb"
}
],
"out":[
{
"value":"0.09800000",
"scriptPubKey":"OP_DUP OP_HASH160 fcc9b36d38cf55d7d5b4ee4dddb6b2c17612f48c OP_EQUALVERIFY OP_CHECKSIG"
}
]
}
@@ -0,0 +1,28 @@
{
"hash":"69216b8aaa35b76d6613e5f527f4858640d986e1046238583bdad79b35e938dc",
"ver":1,
"confirmations":421,
"vin_sz":1,
"vout_sz":2,
"lock_time":0,
"size":226,
"in":[
{
"prev_out":{
"hash":"ab005e03aec91832aefe96ce396eab1f0fb49b1a0e0238613cff265ac7fd512d",
"n":1
},
"scriptSig":"3045022100e4f1a521907e50fc44d33132ee98c9715a64df9d2c2860e3e0474c521ab8537e022030af8d3506a5352e2b056445acd855a42d37270e94a629a7b28b21870ec6d76101 03808c493f061990d2be001e40f048ae8870320b74895ce2d9652f3c1c73cd6f2c"
}
],
"out":[
{
"value":"0.04950000",
"scriptPubKey":"OP_DUP OP_HASH160 fcc9b36d38cf55d7d5b4ee4dddb6b2c17612f48c OP_EQUALVERIFY OP_CHECKSIG"
},
{
"value":"0.04950000",
"scriptPubKey":"OP_DUP OP_HASH160 33cef61749d11ba2adf091a5e045678177fe3a6d OP_EQUALVERIFY OP_CHECKSIG"
}
]
}
@@ -157,10 +157,18 @@
# (SIGHASH_ANYONECANPAY | SIGHASH_SINGLE) p2sh transaction
tx = Bitcoin::P::Tx.from_json(fixtures_file('7208e5edf525f04e705fb3390194e316205b8f995c8c9fcd8c6093abe04fa27d.json'))
p tx.hash == "7208e5edf525f04e705fb3390194e316205b8f995c8c9fcd8c6093abe04fa27d"
tx.hash.should == "7208e5edf525f04e705fb3390194e316205b8f995c8c9fcd8c6093abe04fa27d"
outpoint_tx = Bitcoin::P::Tx.from_json(fixtures_file('3e58b7eed0fdb599019af08578effea25c8666bbe8e200845453cacce6314477.json'))
p outpoint_tx.hash == "3e58b7eed0fdb599019af08578effea25c8666bbe8e200845453cacce6314477"
outpoint_tx.hash.should == "3e58b7eed0fdb599019af08578effea25c8666bbe8e200845453cacce6314477"
tx.verify_input_signature(0, outpoint_tx).should == true
# SIGHHASH_SINGLE - https://bitcointalk.org/index.php?topic=260595.0
tx = Bitcoin::P::Tx.from_json(fixtures_file('315ac7d4c26d69668129cc352851d9389b4a6868f1509c6c8b66bead11e2619f.json'))
tx.hash.should == "315ac7d4c26d69668129cc352851d9389b4a6868f1509c6c8b66bead11e2619f"
outpoint_tx = Bitcoin::P::Tx.from_json(fixtures_file('69216b8aaa35b76d6613e5f527f4858640d986e1046238583bdad79b35e938dc.json'))
outpoint_tx.hash.should == "69216b8aaa35b76d6613e5f527f4858640d986e1046238583bdad79b35e938dc"
tx.verify_input_signature(0, outpoint_tx).should == true
tx.verify_input_signature(1, outpoint_tx).should == true
end
it '#sign_input_signature' do

0 comments on commit 4b8598b

Please sign in to comment.