Bitcoin Forum

Bitcoin => Development & Technical Discussion => Topic started by: Coding Enthusiast on March 31, 2020, 05:59:07 AM



Title: How is OP_CheckSig evaluated when it is inside a SignatureScript?
Post by: Coding Enthusiast on March 31, 2020, 05:59:07 AM
In particular I'm talking about this test vector in bitcoin core:
https://github.com/bitcoin/bitcoin/blob/b53af72b8276e8a23915d38fe459889cccb56f50/src/test/data/tx_valid.json#L167-L169

Code:
["CHECKSIG is legal in scriptSigs"],
[[["ccf7f4053a02e653c36ac75c891b7496d0dc5ce5214f6c913d9cf8f1329ebee0", 0, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]],
"0100000001e0be9e32f1f89c3d916c4f21e55cdcd096741b895cc76ac353e6023a05f4f7cc00000000d86149304602210086e5f736a2c3622ebb62bd9d93d8e5d76508b98be922b97160edc3dcca6d8c47022100b23c312ac232a4473f19d2aeb95ab7bdf2b65518911a0d72d50e38b5dd31dc820121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ac4730440220508fa761865c8abd81244a168392876ee1d94e8ed83897066b5e2df2400dad24022043f5ee7538e87e9c6aef7ef55133d3e51da7cc522830a9c4d736977a76ef755c0121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH"],

SignatureScript is OP_NOP <PushSig1> <PushPub> OP_CheckSig <PushSig2> <PushPub>
PubkeyScript is OP_DUP OP_HASH160 <PushHash> OP_EqualVerify OP_CheckSig

Sig2 verifies as it should (hash digest for signing is the same as ever) but I can't figure out what is being signed for Sig1, using the same PubkeyScript doesn't work (it is also evident from signature being different assuming it was deterministic).


Edit: never mind, I figured it out.
I was removing more than I should have and also was missing the first OP_NOP.
If anyone is interested, this is what the first OP_CheckSig hashes:
Code:
0100000001e0be9e32f1f89c3d916c4f21e55cdcd096741b895cc76ac353e6023a05f4f7cc000000008e6121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ac4730440220508fa761865c8abd81244a168392876ee1d94e8ed83897066b5e2df2400dad24022043f5ee7538e87e9c6aef7ef55133d3e51da7cc522830a9c4d736977a76ef755c0121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a0000000001000000


Title: Re: How is OP_CheckSig evaluated when it is inside a SignatureScript?
Post by: baro77 on March 31, 2020, 08:41:23 AM
Hi! can you elaborate a bit more about the solution? why the OP_NOP is relevant?

thanks
baro


[...]

Edit: never mind, I figured it out.
I was removing more than I should have and also was missing the first OP_NOP.
If anyone is interested, this is what the first OP_CheckSig hashes:
Code:
0100000001e0be9e32f1f89c3d916c4f21e55cdcd096741b895cc76ac353e6023a05f4f7cc000000008e6121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ac4730440220508fa761865c8abd81244a168392876ee1d94e8ed83897066b5e2df2400dad24022043f5ee7538e87e9c6aef7ef55133d3e51da7cc522830a9c4d736977a76ef755c0121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a0000000001000000


Title: Re: How is OP_CheckSig evaluated when it is inside a SignatureScript?
Post by: Coding Enthusiast on March 31, 2020, 10:32:43 AM
Hi! can you elaborate a bit more about the solution? why the OP_NOP is relevant?

I was hard coding test vectors and missed that particular one at the beginning so I was confused about how things should work, that is why it was relevant.
Now I understand the process of executing OP_CheckSig better which goes like this:
- Replace the SignatureScript of the transaction you are verifying with the same script1 that contains that OP_CheckSig.
- Remove all signatures that are the same as the one this OP is verifying because a signature can not sign itself.

So when we want to evaluate Sig1+pub1 in the following script
Code:
OP_Foo OP_Bar <Push_Sig2> <Push_Sig1> <Push_Sig1> <Push_pub1> OP_CheckSig OP_FooBar
We replace the SignatureScript of the transaction with
Code:
OP_Foo OP_Bar <Push_Sig2> <Push_pub1> OP_CheckSig OP_FooBar

Foo Bar ops are any OP code except OP_CodeSeparator.

[1] A tiny little fact that makes a huge difference and is not found in any documentation or at least no clearly.


Title: Re: How is OP_CheckSig evaluated when it is inside a SignatureScript?
Post by: achow101 on March 31, 2020, 04:07:44 PM
OP_CHECKSIG always uses as the scriptCode the subset of script from most recent OP_CODESEPARATOR (or the beginning of the script if there isn't one) to the end of the script with that signature removed. Following this rule, the scriptCode is the entire scriptSig with the signature removed. It will be
Code:
OP_NOP <pubkey> OP_CHECKSIG <sig2> <pubkey>

I added some output to Bitcoin Core's SignatureHash function and it tells me that this is what is being hashed:
Code:
0100000001e0be9e32f1f89c3d916c4f21e55cdcd096741b895cc76ac353e6023a05f4f7cc000000008e6121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ac4730440220508fa761865c8abd81244a168392876ee1d94e8ed83897066b5e2df2400dad24022043f5ee7538e87e9c6aef7ef55133d3e51da7cc522830a9c4d736977a76ef755c0121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a0000000001000000