Bitcoin Forum
September 19, 2019, 05:50:47 PM *
News: Latest Bitcoin Core release: 0.18.1 [Torrent]
 
   Home   Help Search Login Register More  
Pages: [1]
  Print  
Author Topic: Why does P2SH script design look like a hack to me?  (Read 176 times)
Coding Enthusiast
Hero Member
*****
Offline Offline

Activity: 666
Merit: 1031


Novice C♯ Coder


View Profile WWW
July 26, 2019, 03:36:06 PM
Merited by bones261 (2), ETFbitcoin (1), HeRetiK (1), AdolfinWolf (1)
 #1

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:
<PushData-sig><PushData-pubkey>|<Dup><Hash160><PushData-20_byte_hash><EqualVerify><CheckSig>
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><PushData-sig1><PushData-sig2><PushData-redeem_script>|<Hash160><PushData-20_byte_hash><Equal>
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:

<OP_0> => stack has 1 item (emptyBytes)

<PushData-sig1> => stack has 2 item (empty-sig1)

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

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

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

<PushData-20_byte_hash> => stack has 5 items (empty-sig1-sig2-hashresult-givenHash)

<Equal> => 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:
<PushData-sigs><PushData-redeem_script>|<Dup><Hash160><PushData-20_byte_hash><EqualVerify><CheckMultiSig>
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(?)

Projects List+Suggestion box
Donation link using BIP21
Bech32 Donation link!
BitcoinTransactionTool (0.9.2):  Ann - Source Code
Watch Only Bitcoin Wallet (supporting SegWit) (3.1.0):  Ann - Source Code
SharpPusher (broadcast transactions) (0.10.0): Ann - Source Code

1568915447
Hero Member
*
Offline Offline

Posts: 1568915447

View Profile Personal Message (Offline)

Ignore
1568915447
Reply with quote  #2

1568915447
Report to moderator
Advertised sites are not endorsed by the Bitcoin Forum. They may be unsafe, untrustworthy, or illegal in your jurisdiction. Advertise here.
1568915447
Hero Member
*
Offline Offline

Posts: 1568915447

View Profile Personal Message (Offline)

Ignore
1568915447
Reply with quote  #2

1568915447
Report to moderator
achow101
Moderator
Legendary
*
expert
Offline Offline

Activity: 1890
Merit: 2742


bc1qshxkrpe4arppq89fpzm6c0tpdvx5cfkve2c8kl


View Profile WWW
July 26, 2019, 05:24:25 PM
Merited by Welsh (5), dbshck (4), bones261 (2), aliashraf (2), Coding Enthusiast (2), ETFbitcoin (1), HeRetiK (1)
 #2

Now here is another question. Why not simply do this instead:
Code:
<PushData-sigs><PushData-redeem_script>|<Dup><Hash160><PushData-20_byte_hash><EqualVerify><CheckMultiSig>
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:

Recognizing one 'special' form of scriptPubKey and performing extra validation when it is detected is ugly. However, the consensus is that the alternatives are either uglier, are more complex to implement, and/or expand the power of the expression language in dangerous ways.

That could have maybe solve the OP_0 bug(?)
It wouldn't.

Coding Enthusiast
Hero Member
*****
Offline Offline

Activity: 666
Merit: 1031


Novice C♯ Coder


View Profile WWW
July 26, 2019, 06:02:55 PM
Last edit: July 26, 2019, 06:16:26 PM by Coding Enthusiast
 #3

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:
<PushData-redeem_script>|<Hash160><PushData-20_byte_hash><Equal>
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

Projects List+Suggestion box
Donation link using BIP21
Bech32 Donation link!
BitcoinTransactionTool (0.9.2):  Ann - Source Code
Watch Only Bitcoin Wallet (supporting SegWit) (3.1.0):  Ann - Source Code
SharpPusher (broadcast transactions) (0.10.0): Ann - Source Code

achow101
Moderator
Legendary
*
expert
Offline Offline

Activity: 1890
Merit: 2742


bc1qshxkrpe4arppq89fpzm6c0tpdvx5cfkve2c8kl


View Profile WWW
July 26, 2019, 06:35:50 PM
Merited by Coding Enthusiast (2), ETFbitcoin (1)
 #4

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:
<PushData-redeem_script>|<Hash160><PushData-20_byte_hash><Equal>
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.

Coding Enthusiast
Hero Member
*****
Offline Offline

Activity: 666
Merit: 1031


Novice C♯ Coder


View Profile WWW
July 28, 2019, 07:02:44 AM
Merited by Welsh (6), Halab (2), ETFbitcoin (1)
 #5

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.

Projects List+Suggestion box
Donation link using BIP21
Bech32 Donation link!
BitcoinTransactionTool (0.9.2):  Ann - Source Code
Watch Only Bitcoin Wallet (supporting SegWit) (3.1.0):  Ann - Source Code
SharpPusher (broadcast transactions) (0.10.0): Ann - Source Code

Pages: [1]
  Print  
 
Jump to:  

Sponsored by , a Bitcoin-accepting VPN.
Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!