Author

Topic: Why does P2SH script design look like a hack to me? (Read 335 times)

legendary
Activity: 1042
Merit: 2805
Bitcoin and C♯ Enthusiast
Code:
05 52 53 93 55 87 | a9 14 4254e2a76ec94641c2d3e4b5528bbb30a350838c 87
Update:
First hash160 posted in this quote was used to create a new P2SH address (2MyHxGtCH53AhhWTzqwRRCq3MUZ5DahmhRi1) and some testNet coins were sent to this address in this transaction: 4bb9f0a567e83f8ef3b5a18d9b2b19e1139f302471ad03246be50598151d019a
This is the PubScript in this transaction:
a9-14-4254e2a76ec94641c2d3e4b5528bbb30a350838c-87

Then the coins were spent in this transaction: 463782617f0e6a69102530caa9ba2fe48f996128378af99ee437a22660afc5a7
The following is the complete hex dump of it (ScriptSig is in bold):
02000000
01
9a011d159805e56b2403ad7124309f13e1192b9b8da1b5f38e3fe867a5f0b94b
00000000
06
05 52-53-93-55-87
ffffffff
01
a086010000000000
19
76 a9 14 68cfed146aced22f422a68015ff8ca180761912a88ac
00000000


The "script" is the 52-53-93-55-87 (=OP_2 OP_3 OP_ADD OP_5 OP_EQUAL) and is placed in a OP_PUSH (05).
The preceding 06 is the CompactInt size of the whole scriptSig.

1. This address contains coins from 2018, apparently someone else did the same thing as me but never spent the coins. I won't touch them in case some other developer wanted to claim them as an exercise.
staff
Activity: 3458
Merit: 6793
Just writing some code
Thanks, it is starting to make more sense now. 1 more question though, does this mean I can put any "script" in my scriptSig that I want? For example is the following correct:
Code:
|
I am skipping OP_0 since I don't have OP_CHECKMULTISIG and my redeem script is adding 2 + 3 and checks if it is 5:
Code:
05 52 53 93 55 87 | a9 14 4254e2a76ec94641c2d3e4b5528bbb30a350838c 87
Yes, you can have any script as the redeemScript. P2SH allows you to have any arbitrary script be the "locking conditions" without having to expose to the sender exactly what those conditions are and hope that they make the transaction correctly. It also provides a simple and standard way to specify any conditions that you want and still be able to easily receive money.
legendary
Activity: 1042
Merit: 2805
Bitcoin and C♯ Enthusiast
Because that only works for multisig. P2SH allows you to do much more than just multisig. This is not a generic solution at all. Furthermore, you still have to have the "hack" of interpreting the top stack item as a script. The thing that you are calling a "hack" is just part of the literal definition of how to handle a P2SH scriptPubKey. P2SH just defined that a certain sequence of bytes are magic and you must do these specific things to handle them. You say that the script doesn't tell you to keep a copy of the script, but it does, because that's what the sequence of bytes that match the P2SH template means.

Thanks, it is starting to make more sense now. 1 more question though, does this mean I can put any "script" in my scriptSig that I want? For example is the following correct:
Code:
|
I am skipping OP_0 since I don't have OP_CHECKMULTISIG and my redeem script is adding 2 + 3 and checks if it is 5:
Code:
05 52 53 93 55 87 | a9 14 4254e2a76ec94641c2d3e4b5528bbb30a350838c 87
staff
Activity: 3458
Merit: 6793
Just writing some code
Now here is another question. Why not simply do this instead:
Code:
|
Now this would not only make sense but also stick to the already existing design. The script "tells me" to duplicate the redeem script with its OP_DUP so I don't do it on my own, then perform the rest and finally the OP_CHECKMULTISIG consumes 2 items (just like its CheckSig counterpart) and interprets the first as a redeem script and the second as the number of required signatures. It also requires less number of push operations so the transaction can be a little smaller the more signatures it has!
Because that only works for multisig. P2SH allows you to do much more than just multisig. This is not a generic solution at all. Furthermore, you still have to have the "hack" of interpreting the top stack item as a script. The thing that you are calling a "hack" is just part of the literal definition of how to handle a P2SH scriptPubKey. P2SH just defined that a certain sequence of bytes are magic and you must do these specific things to handle them. You say that the script doesn't tell you to keep a copy of the script, but it does, because that's what the sequence of bytes that match the P2SH template means.

Yes, P2SH is kind of a hack, but why they chose this is explained in the BIP itself:

That could have maybe solve the OP_0 bug(?)
It wouldn't.
legendary
Activity: 1042
Merit: 2805
Bitcoin and C♯ Enthusiast
Since I am coding all these things without "translating" it from anywhere, I sometimes face some oddity in decisions that were made. Sometimes I am missing the rationale so here I am...

When looking at P2PKH scripts it all makes perfect sense:
Code:
|
Every "operation" does exactly what it says, they either push some data on top of stack or consume a number of items from the stack and interpret them specifically and give some result.

But then we have multisig/P2SH design the script stops making sense to me (a 2of3 example):
Code:
<0>|
Every operation is doing exactly what they are supposed to except the final PushData operation inside scriptsig! That one is not exactly pushing data, it is pushing a script which I also have to keep a copy of without the script telling me to!!! Which means my script runner now has to have (what I will be calling from now on) a "hack" that copies this last PushData first then runs the whole thing and then runs this last PushData as a script!

Logically running this script (without the hack) should be like this:

=> stack has 1 item (emptyBytes)

=> stack has 2 item (empty-sig1)

=> stack has 3 items (empty-sig1-sig2)

=> stack has 4 items (empty-sig1-sig2-redeemScr)

=> pop top item, hash it, push => stack has 4 items (empty-sig1-sig2-hashresult)

=> stack has 5 items (empty-sig1-sig2-hashresult-givenHash)

=> pop 2 and compare => stack has 4 items (empty-sig1-sig2-true/false)

Without the hack we are left with a stack with 4 items in it and no more operations left to run!

Now here is another question. Why not simply do this instead:
Code:
|
Now this would not only make sense but also stick to the already existing design. The script "tells me" to duplicate the redeem script with its OP_DUP so I don't do it on my own, then perform the rest and finally the OP_CHECKMULTISIG consumes 2 items (just like its CheckSig counterpart) and interprets the first as a redeem script and the second as the number of required signatures. It also requires less number of push operations so the transaction can be a little smaller the more signatures it has! That could have maybe solve the OP_0 bug(?)
Jump to: