Title: What purpose was OP_CODESEPARATOR intended for? Post by: fivebells on November 26, 2011, 01:41:23 PM I get the impression that bitcoin's current implementation has since moved on, but I am curious about the original intent behind the OP_CODESEPARATOR opcode.
More generally,is there a forum or document where early design decisions like this are discussed? (I realize it's unlikely, but it's just possible I've missed it and it would be so useful to have.) Title: Re: What purpose was OP_CODESEPARATOR intended for? Post by: Mike Hearn on November 26, 2011, 02:07:01 PM That's a great question. Unfortunately, the only design document for Bitcoin is the paper written by Satoshi. It covers the basic design but doesn't even mention scripting or contracts. Everything we know about this system has been effectively "rediscovered". Satoshi gave me a brief tutorial in contracts design before he left and the rest I figured out myself.
I spent some time a few months ago trying to figure out OP_CODESEPARATOR. Its definition is clear, but I failed to find any situations in which it would be helpful and I ended up wondering if it was actually mis-designed. We know there are bugs in the scripting system which imply parts of the code was written without ever being really tested. The reasoning is as follows. There are obviously two places you can use an OP_CODESEPARATOR. One is scriptSig and the other is scriptPubKey. There's basically no point putting anything except data blocks in a scriptSig because it's evaluated without anything as input, so, anything that is put there can always be statically evaluated. The exception is if you find a way to represent the result more compactly and thus need lower fees, but from a logic perspective it may as well contain only data. That leaves the scriptPubKey. Putting an OP_CODESEPARATOR here lets you create an "empty space" which the signature wouldn't cover. That's useful only if you can change the contents of that empty space after a signature is created. But you can't, because a signature always covers the COutPoint structure, ie, it contains the hash of the connected transaction, thus you are indirectly signing the contents of that empty space regardless of the presence of a code separator or not. Changing what comes before the separator changes the tx hash and thus breaks any signatures on transactions that were trying to spend that output. It's possible that I have missed something and there is a way to use it I can't see yet. But the indirect-signing thing seems pretty clear. There's no way to sign a spend of a transaction that later changes. If there was, there'd be ways to use the feature. Title: Re: What purpose was OP_CODESEPARATOR intended for? Post by: theymos on November 26, 2011, 03:50:02 PM Hmm... I was thinking you'd use it like this to avoid having signatures depend on one another:
Code: <sigA> <pubkeyA> OP_CHECKSIGVERIFY OP_CODESEPARATOR <sigB> <pubkeyB> OP_CHECKSIG Title: Re: What purpose was OP_CODESEPARATOR intended for? Post by: Mike Hearn on November 27, 2011, 11:18:09 AM How would that work? The act of inserting sigA or sigB changes the hash of the transaction containing the output, invalidating the other signature.
Title: Re: What purpose was OP_CODESEPARATOR intended for? Post by: Gavin Andresen on November 27, 2011, 03:49:54 PM How would that work? The act of inserting sigA or sigB changes the hash of the transaction containing the output, invalidating the other signature. I can't see how OP_CODESEPARATOR can be used, either. I'm tempted to suggest that any transactions using it be 'discouraged' (have miners refuse to build on blocks that contain transactions using it). Transaction hashes might be another, separate discussion topic-- I've been thinking that the way transaction hashes are calculated/used could be improved, although I don't think it is a critical design flaw but in the category of "stuff we can live with but that maybe could have been done better". Title: Re: What purpose was OP_CODESEPARATOR intended for? Post by: fivebells on November 27, 2011, 04:58:34 PM Thanks for the explanations, everyone. That was very helpful.
Title: Re: What purpose was OP_CODESEPARATOR intended for? Post by: theymos on November 27, 2011, 07:44:30 PM How would that work? The act of inserting sigA or sigB changes the hash of the transaction containing the output, invalidating the other signature. I was thinking in terms of a "full" concatenated script, but I've found that pbegincodehash is not preserved between scriptSig and scriptPubKey, so that kind of thing isn't going to work. Is having two checksig/checkmultisig commands in the same script actually even a problem? I'm now thinking that maybe scriptSigs are not even part of the sig hash, which would eliminate the problem entirely. Title: Re: What purpose was OP_CODESEPARATOR intended for? Post by: Mike Hearn on November 28, 2011, 09:56:17 AM I don't think we should discourage it. It's possible there's something we're missing and a use may be discovered in future. The Bitcoin protocol is full of subtleties that aren't immediately apparent. It doesn't seem harmful and it'd be "discouraged" by the IsStandard checks anyway.
A way to refer to a transaction that isn't using its hash could be helpful for some protocols, but I think that would violate all kinds of invariants and make the codebase a lot more complex. It's likely that anything which at first looks like it needs this, can be redesigned to not need it. Title: Re: What purpose was OP_CODESEPARATOR intended for? Post by: Mike Hearn on November 28, 2011, 10:16:45 AM Is having two checksig/checkmultisig commands in the same script actually even a problem? I'm now thinking that maybe scriptSigs are not even part of the sig hash, which would eliminate the problem entirely. It's not a problem as long as the signatures are always in the scriptSig and never in the scriptPubKey. For a while I thought including a signature in the output might allow you to do some neat things like restricting the form of the spending transaction, but it can't work - the signature is calculated in the context of the spending transaction and thus always signs over the hash of the connected transaction, which is the thing you need to insert the signature into. Signatures can't sign themselves. The scripting system is flexible, but not as flexible as it might at first appear - scriptPubKeys can't contain signatures, and whilst scriptSigs are allowed to contain code there's (as far as I can see) no point in doing so. It really is primarily meant for containing signatures. It would have been cool if OP_CHECKSIG allowed for signatures over arbitrary data rather than requiring it to be transaction hashes. However that isn't possible. |