Pages:
Author

Topic: Is this BIP65 sample script standard? - page 3. (Read 4759 times)

legendary
Activity: 1890
Merit: 1086
Ian Knowles - CIYAM Lead Developer
December 29, 2015, 12:25:13 PM
#25
however if at least one txin has a sequence that is not 0xffffffff then the CHECKLOCKTIMEVERIFY wont be bypassed. at worst, you would need to mix in some small satoshis worth of inputs

Not so sure about that as this:

Code:
        // Testing if this vin is not final is sufficient to
        // prevent this condition. Alternatively we could test all
        // inputs, but testing just this input minimizes the data
        // required to prove correct CHECKLOCKTIMEVERIFY execution.
        if (txTo.vin[nIn].IsFinal())
            return false;

Means that it only actually tests the one vin.
legendary
Activity: 1176
Merit: 1134
December 29, 2015, 12:06:35 PM
#24
The one thing that is bothering me (taken from the BIP) is the following:

Code:
        // Finally the nLockTime feature can be disabled and thus
        // CHECKLOCKTIMEVERIFY bypassed if every txin has been
        // finalized by setting nSequence to maxint. The
        // transaction would be allowed into the blockchain, making
        // the opcode ineffective.

I'm not certain how to interpret this but I am concerned if it means that CLTV could be ignored. Can anyone better explain this?


It does seem that if you cant control any of the txin, the nLockTime is just ignored if all sequence id is 0xffffffff (the default value)

for doing micropayment channel and other offchain tx where the same inputs are "reused", the sequence is set to a smaller value and increased, with the 0xffffffff meaning it is finalized, so I think the same logic is used here

however if at least one txin has a sequence that is not 0xffffffff then the CHECKLOCKTIMEVERIFY wont be bypassed. at worst, you would need to mix in some small satoshis worth of inputs

James
legendary
Activity: 1890
Merit: 1086
Ian Knowles - CIYAM Lead Developer
December 29, 2015, 07:43:02 AM
#23
The one thing that is bothering me (taken from the BIP) is the following:

Code:
        // Finally the nLockTime feature can be disabled and thus
        // CHECKLOCKTIMEVERIFY bypassed if every txin has been
        // finalized by setting nSequence to maxint. The
        // transaction would be allowed into the blockchain, making
        // the opcode ineffective.

I'm not certain how to interpret this but I am concerned if it means that CLTV could be ignored. Can anyone better explain this?
legendary
Activity: 1890
Merit: 1086
Ian Knowles - CIYAM Lead Developer
December 29, 2015, 05:26:34 AM
#22
I think we have basically nutted it out (https://webbtc.com/script/7fec1a377344333496cca3d67b06d418f199702cf4a9f5fcb8fbb38c5de963ca:0) where the P2SH script is as follows:

Code:
OP_DUP
OP_SHA256
c775e7b757ede630cd0aa1113bd102661ab38829ca52a6422ab782862f268646
OP_EQUAL
OP_IF
OP_DROP
OP_DUP
OP_HASH160
937fe2ee82229d282edec2606c70e755875334c0
OP_EQUALVERIFY
OP_CHECKSIG
OP_ELSE
c8f505
OP_NOP2
OP_DROP
OP_DUP
OP_HASH160
20fbf78ba8f2f36feaec0efc5b82d5e07fb261a9
OP_EQUALVERIFY
OP_CHECKSIG
OP_ENDIF

This tx has been issued on mainnet with the CLTV refund operating as expected: https://blockchain.info/tx/7fec1a377344333496cca3d67b06d418f199702cf4a9f5fcb8fbb38c5de963ca (thanks to @sonicskye for creating the txs).

Note that c8f505 is the CLTV value that will be checked against nLockTime for the CLTV refund redeem and c775e7b757ede630cd0aa1113bd102661ab38829ca52a6422ab782862f268646 is the hash of the secret that would need to be pushed for the secret revealing refund.

This version uses public key hashes rather than public keys so that you would only need to provide an "address" to the other user (which will be easier for end users to understand).

So the tx can be redeemed immediately by pushing signature 1, public key 1, secret and P2SH script or either at or after the CLTV block by pushing signature 2, public key 2 and the P2SH script (the OP_DUP and OP_DROPs in the P2SH script take care of the stack imbalance when using the CLTV redeem method). Note that nLockTime with a value >= to the CLTV must be provided for the refund redeem to work.
legendary
Activity: 1890
Merit: 1086
Ian Knowles - CIYAM Lead Developer
December 27, 2015, 08:58:01 AM
#21
The script construction is as follows
Quote
OP_DUP OP_SHA256 OP_EQUAL
OP_IF
   OP_DROP
   
   OP_CHECKSIG
OP_ELSE
   
   OP_NOP2
   OP_DROP
   
   OP_CHECKSIG
OP_ENDIF
I have not yet tried redeeming by using the else block, as I think it may work as well.

Anyway, I am wondering if we can just eliminate the OP_DUP and both of the OP_DROP opcodes as there is a redundant secret value to the stack while evaluating the script.

The two OP_DROPs actually do different things so if we want to have the following two ways to do the redeem they have to stay:

1) PUSH PUSH P2SH
(redeem using the secret)

2) PUSH P2SH
(redeem using the CLTV refund - in this case the OP_DUP will actually make a second copy of the )

So the first OP_DROP is because of the redundant secret copy on the stack (in the case of the "reveal secret redeem") but the second one is because of the CLTV value (as in the second case it is expected that only the sig was pushed onto the stack before the P2SH script is executed).

Hope that makes sense and nice to see that the script appears to be running as expected! Smiley
jr. member
Activity: 41
Merit: 3
December 27, 2015, 08:52:25 AM
#20
Yup - by using OP_1 instead of OP_0 it will now always execute the OP_IF steps (and never the OP_ELSE steps) so I think the way I outlined it is the proper way it should be done (to allow for either redeem case).

Presumably it will require the refund redeem tx to push a dummy value (say OP_1) so that the initial OP_SHA256 has something to work with - or perhaps you could instead do an OP_DUP before the initial test with then an extra OP_DROP in the OP_IF steps. Let me try and illustrate the latter.

For the "secret reveal":
Code:
OP                STACK (top is the left)
--                ----------------------
PUSH        
PUSH    
(start of P2SH script)
OP_DUP            
OP_SHA256        
PUSH      
OP_EQUAL          1
OP_IF            
OP_DROP          
PUSH      
OP_CHECKSIG       0 or 1
OP_ENDIF          0 or 1

For the "CLTV refund":
Code:
OP                STACK (top is the left)
--                ----------------------
PUSH        
(start of P2SH script)
OP_DUP            
OP_SHA256        
PUSH      
OP_EQUAL          0
OP_IF            
OP_ELSE          
PUSH      
OP_NOP2          
OP_DROP          
PUSH      
OP_CHECKSIG       0 or 1
OP_ENDIF          0 or 1

Admittedly I have not played around with Bitcoin Script enough to be certain how the stack will behave after each op but I think that should be at least close to correct.


Hi, I created a pair of tx by using your logic https://webbtc.com/script/bd1659576624d937af204f90e153a6be4900650eb8e73d0ca260811435771ed8:0
The script construction is as follows
Quote
OP_DUP OP_SHA256 OP_EQUAL
OP_IF
   OP_DROP
   
   OP_CHECKSIG
OP_ELSE
   
   OP_NOP2
   OP_DROP
   
   OP_CHECKSIG
OP_ENDIF
I have not yet tried redeeming by using the else block, as I think it may work as well.

Anyway, I am wondering if we can just eliminate the OP_DUP and both of the OP_DROP opcodes as there is a redundant secret value to the stack while evaluating the script.
legendary
Activity: 1890
Merit: 1086
Ian Knowles - CIYAM Lead Developer
December 27, 2015, 06:18:15 AM
#19
Yup - by using OP_1 instead of OP_0 it will now always execute the OP_IF steps (and never the OP_ELSE steps) so I think the way I outlined it is the proper way it should be done (to allow for either redeem case).

Presumably it will require the refund redeem tx to push a dummy value (say OP_1) so that the initial OP_SHA256 has something to work with - or perhaps you could instead do an OP_DUP before the initial test with then an extra OP_DROP in the OP_IF steps. Let me try and illustrate the latter.

For the "secret reveal":
Code:
OP                STACK (top is the left)
--                ----------------------
PUSH        
PUSH    
(start of P2SH script)
OP_DUP            
OP_SHA256        
PUSH      
OP_EQUAL          1
OP_IF            
OP_DROP          
PUSH      
OP_CHECKSIG       0 or 1
OP_ENDIF          0 or 1

For the "CLTV refund":
Code:
OP                STACK (top is the left)
--                ----------------------
PUSH        
(start of P2SH script)
OP_DUP            
OP_SHA256        
PUSH      
OP_EQUAL          0
OP_IF            
OP_ELSE          
PUSH      
OP_NOP2          
OP_DROP          
PUSH      
OP_CHECKSIG       0 or 1
OP_ENDIF          0 or 1

Admittedly I have not played around with Bitcoin Script enough to be certain how the stack will behave after each op but I think that should be at least close to correct.
jr. member
Activity: 41
Merit: 3
December 27, 2015, 05:41:20 AM
#18
Again I'm pretty sure that the IF..ELSE shown in the BIP65 example is not the same as OP_IF and OP_ELSE.

The way it reads in the BIP is:

IF
 
ELSE
 
ENDIF

but in Bitcoin Script AFAICT you would need to actually do this:


OP_IF
(where this will be executed if was true)
OP_ELSE
(where these will be executed if was false)

OP_ENDIF

It is odd that you would be having troubles pushing the tx to testnet (as it is more relaxed about things like txs being standard).

I do have a testnet peer running so perhaps I could help with trying to push the raw transactions (and seeing if anything appears to be wrong with say the P2SH address or the like).


I think you are right about this. It really helps me to understand how the conditional script works.

Anyway, here is another tx to study https://webbtc.com/script/1dcdcaad7cb6550170662d7190d4a5cab6c5e3c61e1f289a91331dec4b811835:0
Instead of redeeming the "else" conditional, it entered the "if" block by exposing the secret value.
legendary
Activity: 1890
Merit: 1086
Ian Knowles - CIYAM Lead Developer
December 27, 2015, 04:45:59 AM
#17
Again I'm pretty sure that the IF..ELSE shown in the BIP65 example is not the same as OP_IF and OP_ELSE.

The way it reads in the BIP is:

IF
 
ELSE
 
ENDIF

but in Bitcoin Script AFAICT you would need to actually do this:


OP_IF
(where this will be executed if was true)
OP_ELSE
(where these will be executed if was false)

OP_ENDIF

It is odd that you would be having troubles pushing the tx to testnet (as it is more relaxed about things like txs being standard).

I do have a testnet peer running so perhaps I could help with trying to push the raw transactions (and seeing if anything appears to be wrong with say the P2SH address or the like).
jr. member
Activity: 41
Merit: 3
December 27, 2015, 04:44:09 AM
#16
Yes, when I read the explanation from the link you provided, OP_0 skips the first block in OP_IF. But I think that's what we want from the sample case above.

If we always skip the OP_IF block then you can never redeem with the "secret" - I guess you could perhaps change OP_0 to OP_1 but from what I understand once it has entered OP_IF then it will never execute the OP_ELSE branch (so if you did that then you'd never be able to redeem as the refund).

Thus OP_IF and OP_ELSE do not work perhaps as might have been expected. You have to have done a test before the OP_IF (not just inside it).

Unfortunately it appears that the examples that are illustrated for BIP65 do not show correctly how to use OP_IF (perhaps they were not intended to be read as literal tx scripts at all but just as pseudo code which of course is reasonable).

I think the if..else script in Bitcoin does not work in the same manner as the regular programming language. cmiiw.

So with the script in my previous post I am pretty sure that you could not just provide the secret because the OP_IF steps would be executed if the secret hash was matched (which then results in the signature check for the first public key and the skipping of the OP_ELSE steps).

From what I gather OP_IF will remove the item from the stack but I think that is only in the case of it matching (if that is not the case then the refund would either have to include a dummy extra push or an OP_DUP would need to be used at the start of the script along with an extra OP_DROP in the OP_IF steps).

If the secret hash check fails (which would be the case of course when you don't provide the secret hash which is what the refund tx would do as it would just push the signature onto the stack) then the OP_ELSE steps are executed which would verify the signature against the second public key (after doing the CLTV lock).


Yes, because the sample said that there are 2 possible conditions to redeem the tx; either "publisher" or "buyer" can redeem the tx with different condition as expressed in the if..else script.

It think some careful testing of exactly how this conditional stuff works will be needed - for that I would recommend using "testnet".
I tried testnet, and it was harder to push the tx than the mainnet.
legendary
Activity: 1890
Merit: 1086
Ian Knowles - CIYAM Lead Developer
December 27, 2015, 04:23:27 AM
#15
Yes, when I read the explanation from the link you provided, OP_0 skips the first block in OP_IF. But I think that's what we want from the sample case above.

If we always skip the OP_IF block (in the script as originally shown) then you can never redeem with the "secret" - I guess you could perhaps change OP_0 to OP_1 but from what I understand once it has entered OP_IF then it will never execute the OP_ELSE branch (so if you did that then you'd never be able to redeem as a refund).

Thus OP_IF and OP_ELSE do not work perhaps as might have been expected. You have to have done a test before the OP_IF (whatever happens inside it is not considered as being "the condition").

Unfortunately it appears that the examples that are illustrated for BIP65 do not show correctly how to use OP_IF (perhaps they were not intended to be read as literal tx scripts at all but just as pseudo code which of course is reasonable).

So with the script in my previous post I am pretty sure that you could not just provide the secret because the OP_IF steps would be executed if the secret hash was matched (which then results in the signature check for the first public key and the skipping of the OP_ELSE steps).

From what I gathered OP_IF will remove the item from the stack but I think that is only in the case of it matching (if that is not the case then the refund redeem tx would have to include a dummy extra push).

If the secret hash check fails (which would be the case of course when you don't provide the secret hash which is what the refund tx would do as it would just push the signature onto the stack) then the OP_ELSE steps are executed which would verify the signature against the second public key (after doing the CLTV lock).

It think some careful testing of exactly how this conditional stuff works will be needed - for that I would recommend using "testnet".

Stack based languages like Bitcoin's Script are really not very intuitive to even most programmers. Sad
jr. member
Activity: 41
Merit: 3
December 27, 2015, 04:17:05 AM
#14



I think that the check for the "secret hash" should actually take place before the OP_IF like this:

Code:
OP_SHA256
c775e7b757ede630cd0aa1113bd102661ab38829ca52a6422ab782862f268646
OP_EQUAL[color=red]VERIFY[/color]
OP_IF
OP_DROP (to drop the secret which I am guessing is still on the stack)
03d7c6052544bc42eb2bc0d27c884016adb933f15576a1a2d21cd4dd0f2de0c37d
OP_CHECKSIG
OP_ELSE
389900
OP_NOP2
OP_DROP (drops the block number just used for the NOP2/CLTV test)
021844989a2bd7acd127dd7ed51aa2f4d55b32dbb414de6325ae37e05c1067598d
OP_CHECKSIG
OP_ENDIF

Thus assuming that the "secret hash" is matched we then check the signature for the first public key otherwise we do the CLTV test and check the signature for the second public key.

I am not 100% sure of the stack behaviour so it might be necessary to do either an OP_DUP or have an extra OP_DROP to get that correct.

That case above you probably need to replace the EQUAL with EQUALVERIFY to eliminate "1" value as the result of EQUAL operation. And your script may probably be translated as "between 2 parties, whoever can provide a secret value which matches a certain hash value can redeem the tx". Is that what you want?


I think there is no right or wrong when it comes to the script. It really depends on what you want to achieve with the script. For example, I quoted this from BIP065

Actually looking further into OP_IF I think we have a problem as what is between it and OP_ELSE won't be executed if what is on the top of the stack is empty (which OP_0 would certainly screw up). You can see it illustrated here: https://webbtc.com/script/2bb5d0ac0eb17f5ebe2d660ec47b4888943b4a4f5433c09bd6514b7a36859a95:0 (scroll down to the Execution Trace and you'll see it isn't even executing the OP_SHA256 or first public key signature check).

Yes, when I read the explanation from the link you provided, OP_0 skips the first block in OP_IF. But I think that's what we want from the sample case above.
legendary
Activity: 1890
Merit: 1086
Ian Knowles - CIYAM Lead Developer
December 27, 2015, 02:52:50 AM
#13
Actually looking further into OP_IF I think we have a problem as what is between it and OP_ELSE won't be executed if what is on the top of the stack is empty (which OP_0 would certainly screw up). You can see it illustrated here: https://webbtc.com/script/2bb5d0ac0eb17f5ebe2d660ec47b4888943b4a4f5433c09bd6514b7a36859a95:0 (scroll down to the Execution Trace and you'll see it isn't even executing the OP_SHA256 or first public key signature check).

I think that the check for the "secret hash" should actually take place before the OP_IF like this:

Code:
OP_SHA256
c775e7b757ede630cd0aa1113bd102661ab38829ca52a6422ab782862f268646
OP_EQUAL
OP_IF
OP_DROP (to drop the secret which I am guessing is still on the stack)
03d7c6052544bc42eb2bc0d27c884016adb933f15576a1a2d21cd4dd0f2de0c37d
OP_CHECKSIG
OP_ELSE
389900
OP_NOP2
OP_DROP (drops the block number just used for the NOP2/CLTV test)
021844989a2bd7acd127dd7ed51aa2f4d55b32dbb414de6325ae37e05c1067598d
OP_CHECKSIG
OP_ENDIF

Thus assuming that the "secret hash" is matched we then check the signature for the first public key otherwise we do the CLTV test and check the signature for the second public key.

I am not 100% sure of the stack behaviour so it might be necessary to do either an OP_DUP or have an extra OP_DROP to get that correct.
legendary
Activity: 1890
Merit: 1086
Ian Knowles - CIYAM Lead Developer
December 27, 2015, 01:53:52 AM
#12
Quote
OP_0 is included only to deal with an off-by-one error in Bitcoin Core when using OP_CHECKMULTISIG.

But I am not sure if we must include the OP_0 in P2SH without multisig.

I see - in that case I would be pretty sure that we don't need the OP_0 at all - in fact looking here: https://webbtc.com/script/2bb5d0ac0eb17f5ebe2d660ec47b4888943b4a4f5433c09bd6514b7a36859a95:0 it would appear to me at having OP_0 on the stack is actually causing it to always skip the OP_IF test (another thing that will need to be carefully checked).

For OP_PUSHDATA1, I was trying to construct a redeem tx for P2SH without the mentioned opcode, and it did not succeed.

Doh! Of course - the reason is that you need to push 114 bytes (the P2SH script) onto the stack but a normal PUSH_DATA (which just the length without a specific op code) can only push up to 75 bytes (will edit my earlier post to make this clear).

So apart from setting the "sequence" back to ffffffff I am still skeptical of the way that the CLTV "block number" has been provided (as it is neither in hex nor in he same endian as nLockTime itself is).

I guess a few test txs (which would be best initially done on testnet) to verify the exact format should be played with.
jr. member
Activity: 41
Merit: 3
December 26, 2015, 10:49:48 PM
#11
legendary
Activity: 1890
Merit: 1086
Ian Knowles - CIYAM Lead Developer
December 26, 2015, 10:58:42 AM
#10
BTW - for those who are wondering what the value of getting this stuff right you might want to check this out: http://blog.litecoin.org/2015/12/litecoin-core-v01040.html

Basically Litecoin will soon be accepting CLTV txs as well - so if we can get this ACCT working reliably then you will be able to trade LTC and BTC with any AT supporting platform (currently Qora and Burst).

The Bitcoin/Litecoin side will unfortunately not be so neat (it will require some additional scripts and off-chain communication between the two parties) but it would be a huge step in disbanding the need for crypto-to-crypto exchanges (which is *real disruption* IMO).

Assuming we can get this working in a reliable manner CIYAM will be looking to add support for this special kind of script to its Wallet package.
legendary
Activity: 1890
Merit: 1086
Ian Knowles - CIYAM Lead Developer
December 26, 2015, 06:42:44 AM
#9
So with the help of that online tool and my existing knowledge of the structure of raw transactions I've come up with this complete tx decomposition:

Code:
01000000 (version)
01 (number of inputs)
dfb1ee387eef27d2de91c824a467548a3879dd57691177591474fd2594d8bb23 (previous tx id reversed)
00000000 (previous tx output index)
be (190 bytes - input script length)
------------------------------------------------ 190 bytes ------------------------------------------- Inputs
48 PUSH_DATA (72 bytes - length of signature plus sig type byte)
[
3045 (DER sequence and length)
022100c9e7acd4f39a03acfcfc89438e764c4b5e4d7ab25f155aeb1a60bb47e63e52ad (DER X)
02201daaf42c4fbe3cba3b0c89f87e7aa2dfc5060ad4b44292e8371a2b561d28d42e (DER Y)
01 SIGHASH_ALL
]
00 OP_0 (why do this ???)
4c PUSH_DATA1
72 DATA_LENGTH (114 bytes - P2SH script length)
================================================ 114 bytes =========================================== Script
63 OP_IF
a8 OP_SHA256
20 PUSH_DATA (sha256 of secret)
[
c775e7b757ede630cd0aa1113bd102661ab38829ca52a6422ab782862f268646
]
88 OP_EQUALVERIFY
21 PUSH_DATA (public key)
[
03d7c6052544bc42eb2bc0d27c884016adb933f15576a1a2d21cd4dd0f2de0c37d
]
ac OP_CHECKSIG
67 OP_ELSE
03 PUSH_DATA (block #389900 - or should this be converted to hex and endian encoded???)
[
389900
]
b1 OP_NOP2 (OP_CLTV)
75 OP_DROP
21 PUSH_DATA (public key)
[
021844989a2bd7acd127dd7ed51aa2f4d55b32dbb414de6325ae37e05c1067598d
]
ac OP_CHECKSIG
68 OP_ENDIF
=============================================================================================================
-------------------------------------------------------------------------------------------------------------
5cf40500  (sequence 390236) which should probably be ffffffff
------------------------------------------------- 35 bytes ------------------------------------------ Outputs
01 (number of outputs)
1027000000000000 (value 0.0001 BTC)
19 PUSH_DATA (25 bytes - output script length)
[[
76 OP_DUP
a9 OP_HASH160
14 PUSH_DATA (hash160 of public key - i.e. address)
[
20fbf78ba8f2f36feaec0efc5b82d5e07fb261a9
]
88 OP_EQUALVERIFY
ac OP_CHECKSIG
]]
-------------------------------------------------------------------------------------------------------------
5cf40500 (nLockTime 390236)

So most of it is making sense to me (although it looks as though the sequence number was incorrectly set to the CLTV block #).

Also why is the OP_0 necessary (is this to do with the P2SH that was the output being used from the previous tx)?
legendary
Activity: 1890
Merit: 1086
Ian Knowles - CIYAM Lead Developer
December 26, 2015, 03:32:49 AM
#8
Assuming it is standard then if HASH160 was to be changed to say SHA256 would it still be standard?
https://gist.github.com/gavinandresen/88be40c141bc67acb247

Yup - from reading the code in IsStandardTx I had thought that it should be fine.

The tricky part is hand-crafting raw txs (very easy to get something wrong doing that) so the person helping me out with this is using BX (previously SX).

Basically what I am trying to get worked out is an ACCT tx "template" for Bitcoin that will be compatible with the ACCT AT implementation so that one will be able to exchange QORA or BURST for BTC without an exchange or other 3rd party.
legendary
Activity: 1260
Merit: 1019
December 26, 2015, 03:16:13 AM
#7
Assuming it is standard then if HASH160 was to be changed to say SHA256 would it still be standard?
https://gist.github.com/gavinandresen/88be40c141bc67acb247
legendary
Activity: 1890
Merit: 1086
Ian Knowles - CIYAM Lead Developer
December 26, 2015, 02:39:19 AM
#6
It seems there was something wrong with that redeem script (still trying to work out exactly what) but this one seems to have done the trick:

https://webbtc.com/script/2bb5d0ac0eb17f5ebe2d660ec47b4888943b4a4f5433c09bd6514b7a36859a95:0

Smiley
Pages:
Jump to: