-
-
Save rllola/3a6be4222c7b52f934c28843e7b965aa to your computer and use it in GitHub Desktop.
import ecdsa | |
# https://bitcoin.stackexchange.com/questions/114850/sighash-single-with-no-corresponding-output | |
pubkey = "044edfcf9dfe6c0b5c83d1ab3f78d1b39a46ebac6798e08e19761f5ed89ec83c108172c4776865f02047b39cd704135c00c1b00085e0d1b9255405ac7079fa50a2" | |
signature = "912f994094193109a9faedf7ef855220638f95ac51c66d4eb46740dd1c0813fa100bc99adb8b64fb784173ca8883a78835e156b74f143c02e071dc82695e8472" | |
msg = bytes.fromhex("0100000000000000000000000000000000000000000000000000000000000000") | |
verify_key = ecdsa.VerifyingKey.from_string(bytearray.fromhex(pubkey), curve=ecdsa.SECP256k1) | |
# To verify a digest we need to call a special function because `hashfunc=None` will use the default hashfunc on the msg | |
# see https://github.com/tlsfuzzer/python-ecdsa/blob/5db1d2d2c415b25e741c06451dbc72cb44f75e23/src/ecdsa/keys.py#L671 | |
# verify_key.verify(bytearray.fromhex(signature), msg, hashfunc=None) | |
verify_key.verify_digest(bytes.fromhex(signature), msg) |
It will be accepted by the Bitcoin software. It is a known bug in Bitcoin actually. I can try to explain it.
In the case of sighash single transaction you need to have the number of outputs matching the number of inputs in your transaction. A sighash single transaction without a matching output should not have been considered correct. In the Bitcoin code, it does return an error code 01
. However what happened is that in the code they forgot to check for error code returned by the function and considered 01
to be the message to sign...
01
padded to match 32 bytes is 0100000000000000000000000000000000000000000000000000000000000000
. And that the message that was signed by mistake. To keep consensus it has stayed like this.
The original function in script.cpp
uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType)
{
if (nIn >= txTo.vin.size())
{
printf("ERROR: SignatureHash() : nIn=%d out of range\n", nIn);
return 1;
}
So what should be given to input[0] and [1] as script_sig? Pubkey or HASH_ONE? Let's say for [0] I have my own private key to sign, but what about input[1]?
It depends what are the previous output. Are you trying to build the message to sign ?
I am trying to successfully broadcast a valid transaction (tx). One is mine previous output, second is other output. I am struggling with properly signing the second output while using SIGHASH_SINGLE. For now there lands second output public key, which is not accepted. I suspect there should be HASH_ONE which you have already mentioned - the 0100000000000000000000000000000000000000000000000000000000000000
.
You should never sign the HASH_ONE. It is a bug and people could steal your funds 😅
How many inputs you have and how many ouputs ? If one of the input is not yours you should get the person it belongs to to sign it.
You should never sign the HASH_ONE. It is a bug and people could steal your funds 😅
How many inputs you have and how many ouputs ? If one of the input is not yours you should get the person it belongs to to sign it.
Yes, that's what I am trying to verify - if SIGHASH_SINGLE works.
I have two inputs and one output. He would sign it but we are trying to do the SIGHASH_SINGLE so his signing should be not needed. However I cannot make it work.
You still need the other person to sign the HASH_ONE value. Then people can re-use this signature to steal what funds are left on the address. The signature can be reuse because it sign the simple value 0100000000000000000000000000000000000000000000000000000000000000
(aka HASH_ONE) and not a real unique transaction.
You still need the other person to sign the HASH_ONE value. Then people can re-use this signature to steal what funds are left on the address. The signature can be reuse because it sign the simple value
0100000000000000000000000000000000000000000000000000000000000000
(aka HASH_ONE) and not a real unique transaction.
Ah! You're right! Thank you for explanation! I was missing that info wondering if it is possible to adapt the code. Now I know it is impossible.
Is HASH_ONE hashed/signed always the same?
Yes, you are right!
The remaining problem is if cryptocurrency software will accept it.