Author

Topic: How is OP_CheckSig evaluated when it is inside a SignatureScript? (Read 126 times)

staff
Activity: 3458
Merit: 6793
Just writing some code
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 OP_CHECKSIG

I added some output to Bitcoin Core's SignatureHash function and it tells me that this is what is being hashed:
Code:
0100000001e0be9e32f1f89c3d916c4f21e55cdcd096741b895cc76ac353e6023a05f4f7cc000000008e6121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ac4730440220508fa761865c8abd81244a168392876ee1d94e8ed83897066b5e2df2400dad24022043f5ee7538e87e9c6aef7ef55133d3e51da7cc522830a9c4d736977a76ef755c0121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a0000000001000000
legendary
Activity: 1042
Merit: 2805
Bitcoin and C♯ Enthusiast
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 OP_CheckSig OP_FooBar
We replace the SignatureScript of the transaction with
Code:
OP_Foo OP_Bar 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.
member
Activity: 90
Merit: 91
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
legendary
Activity: 1042
Merit: 2805
Bitcoin and C♯ Enthusiast
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 OP_CheckSig
PubkeyScript is OP_DUP OP_HASH160 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
Jump to: