Author

Topic: Bitcoin Core doesn't sign with Sighash_Single if index is smaller than outcount (Read 211 times)

legendary
Activity: 1042
Merit: 2805
Bitcoin and C♯ Enthusiast
Yeah, I figured it must have something to do with the way core deals with hashes.
The wiki article however should either use the correct form when it calls it a "hash" or be explicit about the endianness and the type of it (being uint256).
Someone with edit access should clarify it IMO.
staff
Activity: 3458
Merit: 6793
Just writing some code
I'm confused about why bitcoin wiki is stating that the bytes to sign (or hash) should be
Code:
0000000000000000000000000000000000000000000000000000000000000001
Because that's what the source code says: https://github.com/bitcoin/bitcoin/blob/master/src/script/interpreter.cpp#L1284. But the behavior of uint256S in Bitcoin Core can be confusing.

whereas it is the exact opposite meaning what you sign is:
Code:
0100000000000000000000000000000000000000000000000000000000000000
That's just a little endian 1. Uint256S byteswaps its input, so the big endian 1 that is provided earlier is byteswapped into a little endian 1.
legendary
Activity: 1042
Merit: 2805
Bitcoin and C♯ Enthusiast
I'm confused about why bitcoin wiki is stating that the bytes to sign (or hash) should be
Code:
0000000000000000000000000000000000000000000000000000000000000001
whereas it is the exact opposite meaning what you sign is:
Code:
0100000000000000000000000000000000000000000000000000000000000000
meaning a byte array of length 32 and value 1 is set in its first position!


Here is the test transaction:
TxId: https://live.blockcypher.com/btc-testnet/tx/a9bc0f6129bc552379a20ab2a4b6a79ccc2d713acc99bf1b116939393646a5c3/
Third input signature was generated this way:
Code:
Message (hex): 0100000000000000000000000000000000000000000000000000000000000000
e (integer): 452312848583266388373324160190187140051835877600158453279131187530910662656
k (integer): 32569526756695674143942276415017767656920268428945073886134926826167993959331
key (integer): 84383840204293825554234399499853084747046055893341335473786835522085952287264

R: 00d22c986e5ccdf63c5714dafb24b73651d8658a3d2f185b39d82d8d1db93ff7d3
S: 0709f363ab3f36ca1fe01707fb018f5307f59a943a79b3fa101aa7a010905589
SigHashType: 03
Pubkey: 0305b3f3dc092ba4f8d79a16088dddd1fffb68871f590c69a2ebc4145be0ca648e

As it can be seen from e we aren't signing "1", we are signing 4523....56


And finally here is another one with both Single and AnyoneCanPay:
https://live.blockcypher.com/btc-testnet/tx/5b869dd7433a696b34a9ab3f86723ee2e04aad90932ddfa9d72734171a57961b/
staff
Activity: 3458
Merit: 6793
Just writing some code
Signing with SIGHASH_SINGLE for inputs that don't have a corresponding output is explicitly disallowed as it is unsafe since it signed "1" and not the transaction.

The only way to work around this is to sign using other software.
legendary
Activity: 1042
Merit: 2805
Bitcoin and C♯ Enthusiast
I'm testing edge cases:
Code:
signrawtransaction "0100000003993c71b921a95716fa0edfe46d0facd246b8b4d3ee3f0147c526194a1bc5654a01000000009bfffffffa8c89ca6adf7e05fbe85cd84a8c876943aad26c2a1fa39fe00af2e20789e584000000000037ffffff56756fc8abc4b063a2bfbd1890a3c50c77c20bd7d0040002b1324d618f41140a0100000000d3feffff0230561a00000000001976a91433504f2fb2c368480cfba7530757d14c41c8960788ac40420f00000000001976a9147adb657ea875b9d684bbb43e528d7f120ffa67f988ac060d1800" '[{"txid":"0a14418f614d32b1020004d0d70bc2770cc5a39018bdbfa263b0c4abc86f7556","vout":1, "scriptPubKey":"76a91435d70ed960e3f83f83251a519cbc40178ff90d0788ac"}]' '["_key_removed_on_purpose_"]' 'SINGLE'
It is signing the third input with Sighash_Single (same with |AnyoneCanPay added) while having 2 outputs

This was bitcoin core 16.3 and it fails:
Code:
"Unable to sign input, invalid stack size (possibly missing key)"
Signing works with other SigHashTypes

The way I understand, this is allowed in protocol, it just doesn't make sense to sign this way (not having an actual txout to sign with Single!) and it should sign 32 byte long "1" instead.
Am I missing something or is it intentionally being rejected since it doesn't make sense to sign like this? If intentional is there any workaround other than signing with my code and broadcasting to see if it is rejected?
Jump to: