pooya87 (OP)
Legendary
Offline
Activity: 3626
Merit: 11029
Crypto Swap Exchange
|
|
December 08, 2021, 05:32:47 AM |
|
I never could figure out where would OP_CODESEPARATOR be useful and some very old comments from early days suggest it may be a byproduct of a bad decision (eg. scripts were concatenated then executed at first). While going through Taproot this OP code makes even less sense in Tapscripts and yet it is there. So I was wondering if I'm missing something and whether there is any good script examples I could look at where OP_CODESEPARATOR solves a problem that can't be solved in any other way.
|
|
|
|
NotATether
Legendary
Offline
Activity: 1778
Merit: 7374
Top Crypto Casino
|
|
December 08, 2021, 05:47:29 AM |
|
Looking at this diagram of OP_CHECKSIG steps and the Bitcoin Script wiki, OP_CODESEPARATOR is used to make OP_CHECKSIG check only part of the scriptPubKey. Essentially, only the script that goes after the last OP_CODESEPARATOR is used to sign the transaction and hence evaluated by OP_CHECKSIG. In theory, a spending transaction could change the part of the scriptPubKey before the last OP_CODESEPARATOR of the input transaction. However, there's a problem. Since scriptPubKey comes from the input transaction, you can't actually modify any part of the scriptPubKey (even the part before the last OP_CODESEPARATOR) without changing the input transaction hash. Changing the input transaction hash breaks the link for any transaction trying to spend outputs from the unspent input transaction, making it impossible to use OP_CODESEPARATOR in practice. I wasn't able to find any cases in practice where people have successfully used OP_CODESEPARATOR for a useful purpose, although it does show up in the blockchain. See this, this and this (and the thread you referenced) for core developers commenting on or discussing possible uses for OP_CODESEPARATOR. It has no practical use because it has a side effect that any part of the public key you modify will change the transaction hash. Granted, I've only ever seen OP_CODESEPARATOR scripts inside Bitcoin Core unit tests.
|
|
|
|
pooya87 (OP)
Legendary
Offline
Activity: 3626
Merit: 11029
Crypto Swap Exchange
|
|
December 08, 2021, 06:20:07 AM |
|
I'm aware of the mechanics, the same mechanics that no longer exist in Tapscripts since the script is no longer changed, we just add the OP position to the bytes we are hashing when computing the sighash. Which raises the question of why wasn't this OP code removed/disabled like OP_CHECKMULTISIG(VERIFY). It has no practical use because it has a side effect that any part of the public key you modify will change the transaction hash.
You don't need to modify the pubkey scripts and also there are redeem scripts that this OP code could be used in. And it seems that there are some use cases (which still don't make sense to me since there are alternative ways) that this OP code could come in play so I'm hoping for more or better examples. Example: https://lists.linuxfoundation.org/pipermail/lightning-dev/2016-March/000455.html
|
|
|
|
garlonicon
Copper Member
Legendary
Offline
Activity: 923
Merit: 2214
Pawns are the soul of chess
|
|
December 08, 2021, 06:30:46 AM |
|
If you have "<pubkey> OP_CHECKSIG" in scriptPubKey and "<sig>" in scriptSig, you don't need OP_CODESEPARATOR. But if you have "<sig> <pubkey> OP_CHECKSIG" in scriptPubKey, then your signature has to sign itself, because you put scriptPubKey of the previous output when calculating z-value to sign for transaction. On the other hand, if you have "<sig> OP_CODESEPARATOR <pubkey> OP_CHECKSIG" in scriptPubKey, then your z-value is independent from your "<sig>", which means you can put signatures in your output scripts.
The practical use case I can think of is to limit possible transactions, where you can spend your input. If your "<sig>" uses SIGHASH_ALL, that means you can pre-calculate your next transaction, get your z-value, make a signature, and then create your output, that will be spendable only in this pre-computed transaction and nowhere else. Probably, if you combine it with other sighashes or use some kind of OP_IF or OP_PICK to choose one of N signatures from scriptPubKey, then you can decide, in which of N transactions your input can be included.
|
|
|
|
pooya87 (OP)
Legendary
Offline
Activity: 3626
Merit: 11029
Crypto Swap Exchange
|
|
December 08, 2021, 06:41:46 AM |
|
But if you have "<sig> <pubkey> OP_CHECKSIG" in scriptPubKey, then your signature has to sign itself,
No you don't. When computing sighash (for legacy and witness version 0) the FindAndDelete method is called which would remove the signature. So the script that would be used in signing becomes " <pubkey> OP_CHECKSIG". For witness version 1 (Tapscripts) things are very different and the leaf hash is used.
|
|
|
|
vjudeu
Copper Member
Legendary
Offline
Activity: 900
Merit: 2243
|
|
December 17, 2021, 02:23:00 PM |
|
This is a great question, but I am worried, that the answer could be "no", when it comes to "a problem that can't be solved in any other way".
|
|
|
|
|
RobinLinus
Newbie
Offline
Activity: 20
Merit: 39
|
|
February 12, 2022, 11:03:31 AM |
|
I never could figure out where would OP_CODESEPARATOR be useful and some very old comments from early days suggest it may be a byproduct of a bad decision (eg. scripts were concatenated then executed at first). While going through Taproot this OP code makes even less sense in Tapscripts and yet it is there. So I was wondering if I'm missing something and whether there is any good script examples I could look at where OP_CODESEPARATOR solves a problem that can't be solved in any other way.
Here is an example how you could use it in an interesting way: https://github.com/coins/bitcoin-scripts/blob/master/op-codeseparator.md
|
|
|
|
pooya87 (OP)
Legendary
Offline
Activity: 3626
Merit: 11029
Crypto Swap Exchange
|
|
February 13, 2022, 03:58:39 AM Merited by vapourminer (1) |
|
I think I saw this 2 months ago when I started the topic and it still doesn't make any sense. Take the last example: OP_IF # Case 1 OP_CODESEPARATOR 600300 OP_ENDIF
OP_IF # Case 2 OP_CODESEPARATOR 600200 OP_ENDIF
OP_IF # Case 3 OP_CODESEPARATOR 600100 OP_ENDIF
OP_CHECKLOCKTIMEVERIFY OP_DROP
2 <Alice.Pubkey> <Bob.Pubkey> 2 OP_CHECKMULTISIG
When you spend it with something like <Bob.SignatureCase1> <Alice.SignatureCase1> 0 0 1
The first IF pops 1 but the second IF is not popping the 0, instead it pops 600300 that was pushed to the stack inside the conditional branch! And OP_CODESEPARATOR doesn't seem to be doing anything here. Then 600200 will be pushed to the stack to be popped by the next IF and finally 600100 which will be popped by OP_CHECKLOCKTIMEVERIFY. So why not use a nested IF? OP_IF 600300 OP_ELSE OP_IF 600200 OP_ELSE 600100 OP_ENDIF OP_ENDIF
OP_CHECKLOCKTIMEVERIFY OP_DROP
2 <Alice.Pubkey> <Bob.Pubkey> 2 OP_CHECKMULTISIG
It is shorter and achieves the same thing without OP_CODESEPARATOR.
|
|
|
|
garlonicon
Copper Member
Legendary
Offline
Activity: 923
Merit: 2214
Pawns are the soul of chess
|
So why not use a nested IF? Maybe no IF is needed at all if there are many cases. Something like this should solve it: scriptPubKey: OP_TOALTSTACK OP_CODESEPARATOR 600300 600200 600100 OP_FROMALTSTACK OP_PICK OP_CHECKLOCKTIMEVERIFY OP_2DROP OP_2DROP 2 <Alice.Pubkey> <Bob.Pubkey> 2 OP_CHECKMULTISIG scriptSig: <Bob.SignatureCase1> <Alice.SignatureCase1> 1
|
|
|
|
pooya87 (OP)
Legendary
Offline
Activity: 3626
Merit: 11029
Crypto Swap Exchange
|
|
February 13, 2022, 10:04:34 AM Merited by garlonicon (2) |
|
So why not use a nested IF? Maybe no IF is needed at all if there are many cases. Something like this should solve it: scriptPubKey: OP_TOALTSTACK OP_CODESEPARATOR 600300 600200 600100 OP_FROMALTSTACK OP_PICK OP_CHECKLOCKTIMEVERIFY OP_2DROP OP_2DROP 2 <Alice.Pubkey> <Bob.Pubkey> 2 OP_CHECKMULTISIG scriptSig: <Bob.SignatureCase1> <Alice.SignatureCase1> 1 That's an interesting approach for the same script but why use OP_CODESEPARATOR here at all? It doesn't change anything apart from affecting whether or not you hash OP_TOALTSTACK while computing the sighash which seems pointless to me.
|
|
|
|
garlonicon
Copper Member
Legendary
Offline
Activity: 923
Merit: 2214
Pawns are the soul of chess
|
|
February 13, 2022, 10:16:52 AM |
|
why use OP_CODESEPARATOR here at all? Good point, maybe it should be placed between OP_PICK and OP_CHECKLOCKTIMEVERIFY? I am not sure, it needs more testing.
|
|
|
|
vjudeu
Copper Member
Legendary
Offline
Activity: 900
Merit: 2243
|
I think I found some use case for OP_CODESEPARATOR: it allows you to sign some unknown script, chosen by the second party, as long as the transaction will match your signature (including your sighashes, not limited to SIGHASH_ALL). So, if you will have "OP_CODESEPARATOR <yourPubKey> OP_CHECKSIG", then only that part will be signed. By getting previous transaction hash and index from the second party, as long as you generated a fresh private key that was never used, you can safely provide your public key, then another party will prepare a transaction, and you can sign it. Then, there is no way to cheat, because the other party can only block coins, but not steal them (because there is no OP_SUCCESS outside TapScript). Edit: Also, what about this? <locktimeAlice> OP_CODESEPARATOR OP_CHECKLOCKTIMEVERIFY OP_DROP <alicePubKey> OP_CHECKSIGVERIFY <locktimeBob> OP_CODESEPARATOR OP_CHECKLOCKTIMEVERIFY OP_DROP <bobPubKey> OP_CHECKSIG
|
|
|
|
pooya87 (OP)
Legendary
Offline
Activity: 3626
Merit: 11029
Crypto Swap Exchange
|
|
June 27, 2022, 03:01:08 AM |
|
Edit: Also, what about this? <locktimeAlice> OP_CODESEPARATOR OP_CHECKLOCKTIMEVERIFY OP_DROP <alicePubKey> OP_CHECKSIGVERIFY <locktimeBob> OP_CODESEPARATOR OP_CHECKLOCKTIMEVERIFY OP_DROP <bobPubKey> OP_CHECKSIG The first time value (locktimeAlice) is pointless since it will never be signed by any of the keys so it can be changed to any value by anyone. Apart from that, it was interesting.
|
|
|
|
vjudeu
Copper Member
Legendary
Offline
Activity: 900
Merit: 2243
|
|
June 27, 2022, 04:32:58 AM Last edit: June 27, 2022, 04:50:06 AM by vjudeu Merited by vapourminer (2) |
|
The first time value (locktimeAlice) is pointless since it will never be signed by any of the keys so it can be changed to any value by anyone. Apart from that, it was interesting. That's the point. Imagine that Alice and Bob signed some script that was prepared by Charlie, so they don't have to know the opcodes that were before. They only need a previous transaction hash and a previous index, by having those 36 bytes, they can sign it with any sighashes (also note that Alice can use different sighashes than Bob, that's another interesting part of multisig, that is not widely explored, because you cannot concatenate multisigs with different sighashes into a single signature). Also note what is signed by Bob, so how many opcodes is needed to pass to him. And imagine there are N people, where each of them can know only some part of the script. It could also work with Taproot, but then, there is a need to prove that no OP_SUCCESS is present in any previous opcodes. Edit: Also note that the previous transaction hash can be used to reveal only some part of the previous transaction. For example, it is possible to reveal the result of the first SHA-256 only. It is possible to reveal that, and the last SHA-256 block (then, it is possible to know some last bytes, the size of the whole transaction, and the hash of the previous part). SHA-256 is executed in 512-bit blocks. That can be used to form very interesting protocols, because you can reveal some parts of the message, and hide the rest, as long as you can set any Initialization Vector and any Exit Hash, and require revealing a matching part in-between, you can cryptographically force another party to cooperate. Unfortunately, the current Script allows only executing hash functions with default IVs (but still, it can be used to compute in-between hashes, and then require revealing some partial messages).
|
|
|
|
pooya87 (OP)
Legendary
Offline
Activity: 3626
Merit: 11029
Crypto Swap Exchange
|
That's the point. Imagine that Alice and Bob signed some script that was prepared by Charlie, so they don't have to know the opcodes that were before.
I understood that, my point was that since Alice is seeing and signing OP_CHECKLOCKTIMEVERIFY, she also has to see and sign the locktime value or OP_CODESEPARATOR has to come after OP_CLV so that Alice doesn't even see that OP code to know there is a locktime involved. P.S. Now that I look at it again, only the part where I said "locktime value can be changed" was wrong since the script is protected by the hash of the it found in the output script that is being spent.
|
|
|
|
vjudeu
Copper Member
Legendary
Offline
Activity: 900
Merit: 2243
|
|
June 27, 2022, 12:13:30 PM Last edit: June 27, 2022, 12:42:41 PM by vjudeu Merited by vapourminer (2) |
|
P.S. Now that I look at it again, only the part where I said "locktime value can be changed" was wrong since the script is protected by the hash of the it found in the output script that is being spent. You can still change it, if it will be a part of the input script. And note you have opcodes like OP_MIN, OP_MAX or OP_WITHIN. Edit: Also, there is another thing planned, called SIGHASH_ANYPREVOUT. Or rather, it could be a little more complex: "txid:vout" can be used to select the output, and then tweaked accordingly, by changing the previous transaction: SIGHASH_PREVOUT_ALL (default, no change), SIGHASH_PREVOUT_SINGLE (sign only one corresponding input, selected by vout), SIGHASH_PREVOUT_NONE (sign no inputs of the previous transaction), SIGHASH_PREVOUT_ANYONECANPAY (sign only this "txid:vout", all other outputs cleared, can be combined with other sighashes). Then, it could be possible to create a chain of transaction, that would allow "flow control", because you could use SIGHASH_PREVOUT_NONE|SIGHASH_PREVOUT_ANYONECANPAY, and make it resistant to any changes of the previous transaction inputs and outputs (but still, fields like version and locktime will still be signed in that case).
|
|
|
|
Zilon
|
|
June 27, 2022, 06:21:17 PM |
|
You can still change it, if it will be a part of the input script. And note you have opcodes like OP_MIN, OP_MAX or OP_WITHIN.
Input script that validates the spending signature i guess?. How about in cases of Op_Hash160 where the input is encoded twice how would this change get into the input script will there be room for this time lock to get an OP_MIN, OP_MAX or OP_WITHIN Edit: Also, there is another thing planned, called SIGHASH_ANYPREVOUT. Or rather, it could be a little more complex: "txid:vout" can be used to select the output, and then tweaked accordingly, by changing the previous transaction:
SIGHASH_PREVOUT_ALL (default, no change), SIGHASH_PREVOUT_SINGLE (sign only one corresponding input, selected by vout), SIGHASH_PREVOUT_NONE (sign no inputs of the previous transaction), SIGHASH_PREVOUT_ANYONECANPAY (sign only this "txid:vout", all other outputs cleared, can be combined with other sighashes).
Then, it could be possible to create a chain of transaction, that would allow "flow control", because you could use SIGHASH_PREVOUT_NONE|SIGHASH_PREVOUT_ANYONECANPAY, and make it resistant to any changes of the previous transaction inputs and outputs (but still, fields like version and locktime will still be signed in that case).
I thought this hashes are scrambled using the timelock how then will it be recalculated so as to make changes on the previous transaction
|
|
|
|
Majestic-milf
|
|
June 27, 2022, 06:51:55 PM |
|
They only need a previous transaction hash and a previous index Which in this case is the pre-image hash? Because Bob will not be able to access the funds without them. Now for the case of "txid:vout", you will have to provide a script as proof that it was committed to by the output.
|
| █▄ | R |
▀▀▀▀▀▀▀██████▄▄ ████████████████ ▀▀▀▀█████▀▀▀█████ ████████▌███▐████ ▄▄▄▄█████▄▄▄█████ ████████████████ ▄▄▄▄▄▄▄██████▀▀ | LLBIT | ▀█ | THE #1 SOLANA CASINO | ████████████▄ ▀▀██████▀▀███ ██▄▄▀▀▄▄█████ █████████████ █████████████ ███▀█████████ ▀▄▄██████████ █████████████ █████████████ █████████████ █████████████ █████████████ ████████████▀ | ████████████▄ ▀▀▀▀▀▀▀██████ █████████████ ▄████████████ ██▄██████████ ████▄████████ █████████████ █░▀▀█████████ ▀▀███████████ █████▄███████ ████▀▄▀██████ ▄▄▄▄▄▄▄██████ ████████████▀ | ........5,000+........ GAMES ......INSTANT...... WITHDRAWALS | ..........HUGE.......... REWARDS ............VIP............ PROGRAM | . PLAY NOW |
|
|
|
pooya87 (OP)
Legendary
Offline
Activity: 3626
Merit: 11029
Crypto Swap Exchange
|
|
June 28, 2022, 03:06:58 AM |
|
You can still change it, if it will be a part of the input script.
I don't see how. If for example you are spending a P2SH or P2WSH output, the hash of the entire script is already locked in the previous transaction being spent and can not change without changing that transaction also.
|
|
|
|
|