Difference between revisions of "Scripts with Flow Control (Conditional Clauses)"

(Created page with "Conditional clauses are implemented in Bitcoin script using IF/NOTIF statements. There are several varieties of these clauses that can be used to build if statements in Bitcoi...")
 
 
(8 intermediate revisions by one other user not shown)
Line 10: Line 10:
  
 
==OP_VERIF, OP_VERNOTIF==
 
==OP_VERIF, OP_VERNOTIF==
OP_VERIF will execute the set of subsequent opcodes up-to the following OP_ELSE or OP_ENDIF if the value on top of the stack matches the protocol VERSION indicated in the transaction serialisation string. Some, or all network nodes may refuse to evaluate certain protocol versions meaning transactions using these parameters must be careful.  
+
'''NOTE: OP_VERIF and OP_VERNOTIF are currently disabled in the BitcoinSV mining client and transactions that use them in executed script will fail'''
 +
 
 +
OP_VERIF will execute the set of subsequent opcodes up-to the following OP_ELSE or OP_ENDIF if the value on top of the stack matches the protocol VERSION. Some, or all network nodes may refuse to evaluate certain protocol versions meaning transactions using these parameters must be careful.  
 
Similarly, OP_VERNOTIF will execute the set of subsequent opcodes up-to the following OP_ELSE or OP_ENDIF if the value on top of the stack does not match the protocol VERSION indicated in the transaction serialisation string.
 
Similarly, OP_VERNOTIF will execute the set of subsequent opcodes up-to the following OP_ELSE or OP_ENDIF if the value on top of the stack does not match the protocol VERSION indicated in the transaction serialisation string.
 
Similarly to OP_IF/OP_NOTIF, ifan OP_ELSE is the subsequent conditional clause and the first conditional clause was successful, the script will jump forward to the OP_ENDIF at the conditional-stack height of the original clause. the script will jump to the subsequent opcode following the else on a failure of the conditional entry.
 
Similarly to OP_IF/OP_NOTIF, ifan OP_ELSE is the subsequent conditional clause and the first conditional clause was successful, the script will jump forward to the OP_ENDIF at the conditional-stack height of the original clause. the script will jump to the subsequent opcode following the else on a failure of the conditional entry.
 
The loop concludes after an OP_ENDIF is processed.
 
The loop concludes after an OP_ENDIF is processed.
 
  
 
==Example 1==
 
==Example 1==
 
The following example uses IF, ELSE and ENDIF statements to manage four possible ScriptSigs which can unlock this output.  
 
The following example uses IF, ELSE and ENDIF statements to manage four possible ScriptSigs which can unlock this output.  
  
ScriptSig1:    <sig1> <pk1> 1
+
    ScriptSig1:    <sig1> <pk1> 1
ScriptSig2:    <sig2> <pk2> 2
+
    ScriptSig2:    <sig2> <pk2> 2
ScriptSig3:    <sig3> <pk3> 3
+
    ScriptSig3:    <sig3> <pk3> 3
ScriptSig4:    <sigRP> <pkRP>
+
    ScriptSig4:    <sigRP> <pkRP>
  
 
The first three are PKH signatures with a numeric signal to show which conditional loop to enter for evaluation. Depending on which numeric signal is present, the script will enter the relevant height conditional clause. Each subsequent conditional IF statement is nested inside the else statement of the preceding level. If no numeric signal is present, the script goes into the third level else statement where the ScriptSig is tested against an R-Puzzle Hash and the script exits the loops.
 
The first three are PKH signatures with a numeric signal to show which conditional loop to enter for evaluation. Depending on which numeric signal is present, the script will enter the relevant height conditional clause. Each subsequent conditional IF statement is nested inside the else statement of the preceding level. If no numeric signal is present, the script goes into the third level else statement where the ScriptSig is tested against an R-Puzzle Hash and the script exits the loops.
  
ScriptPubKey:
+
    DUP 1 EQUAL IF
DUP 1 EQUAL IF
+
        DROP DUP HASH160 <PKH1> EQUALVERIFY CHECKSIG
    DROP DUP HASH160 <PKH1> EQUALVERIFY CHECKSIG
 
ELSE
 
    DUP 2 EQUAL IF
 
            DROP DUP HASH160 <PKH2> EQUALVERIFY CHECKSIG
 
 
     ELSE
 
     ELSE
         DUP 3 EQUAL IF
+
         DUP 2 EQUAL IF
            DROP DUP HASH160 <PKH3> EQUALVERIFY CHECKSIG
+
                DROP DUP HASH160 <PKH2> EQUALVERIFY CHECKSIG
 
         ELSE
 
         ELSE
             OVER 3 SPLIT SWAP DROP 1 SPLIT SWAP SPLIT DROP HASH160 <RPH> EQUALVERIFY CHECKSIG
+
             DUP 3 EQUAL IF
 +
                DROP DUP HASH160 <PKH3> EQUALVERIFY CHECKSIG
 +
            ELSE
 +
                OVER 3 SPLIT SWAP DROP 1 SPLIT SWAP SPLIT DROP HASH160 <RPH> EQUALVERIFY CHECKSIG
 +
            ENDIF
 
         ENDIF
 
         ENDIF
 
     ENDIF
 
     ENDIF
ENDIF
 
  
 
==Example 2==
 
==Example 2==
 
In this example, three possible ScriptSigs are accomodated. The entry to the conditional clauses is based on the depth of the stack subsequent to the processing of the ScriptSig.
 
In this example, three possible ScriptSigs are accomodated. The entry to the conditional clauses is based on the depth of the stack subsequent to the processing of the ScriptSig.
  
ScriptSig1:    <SIG> <PK>
+
    ScriptSig1:    <SIG> <PK>
ScriptSig2:    1 <SIG1> <SIG3> <SIG4 <PK1> <PK2> <PK3> <PK4> <PK5>
+
    ScriptSig2:    1 <SIG1> <SIG3> <SIG4>
ScriptSig3:    <PASSWORD> <SIG6> <PK6>
+
    ScriptSig3:    <PASSWORD> <SIG6> <PK6>
  
Either of the first two ScriptSigs are evaluated in their own separate IF loops which exit using RETURN statements. If the ScriptSig has a stack depth that doesn't match either of the requirements, it passes through to a final evaluation.
+
Either of the first two ScriptSigs are evaluated in their own separate IF loops which exit using RETURN statements. If the ScriptSig has a stack depth that doesn't match either of the requirements, it passes through to a final evaluation which must have a different signature and a backup password.
  
DEPTH 2 EQUAL IF
+
    DEPTH 2 EQUAL IF
    DUP HASH160 EQUALVERIFY CHECKSIG RETURN
+
        DUP HASH160 EQUALVERIFY CHECKSIG RETURN
ENDIF
+
    ENDIF
DEPTH 9 EQUAL IF
+
    DEPTH 4 EQUAL IF
    TOALTSTACK TOALTSTACK TOALTSTACK TOALTSTACK 3 SWAP DUP HASH160 <PKH1>
+
      <PK1> <PK2> <PK3> <PK4> <PK5> 5 CHECKMULTISIG RETURN
    EQUALVERIFY FROMALTSTACK DUP HASH160 <PKH2> EQUALVERIFY FROMALTSTACK
+
    ENDIF
    DUP HASH160 <PKH3> EQUALVERIFY FROMALTSTACK DUP HASH160 <PKH4> EQUALVERIFY
+
    DUP HASH160 <PKH6> EQUALVERIFY CHECKSIGVERIFY SHA256 <PASSWORDHASH> EQUAL RETURN
    FROMALTSTACK DUP HASH160 <PKH5> EQUALVERIFY 5 CHECKMULTISIG RETURN
 
ENDIF
 
OVER 3 SPLIT NIP 1 SPLIT SWAP SPLIT DROP 10 SPLIT DROP 0 NUMEQUALVERIFY DUP
 
HASH160 <PKH6> EQUALVERIFY SHA256 <PASSWORDHASH> EQUAL RETURN
 

Latest revision as of 11:08, 19 February 2020

Conditional clauses are implemented in Bitcoin script using IF/NOTIF statements. There are several varieties of these clauses that can be used to build if statements in Bitcoin. Conditional clauses use the third stack in the Script validation engine to manage nested conditions making sure that OP_ELSE or OP_ENDIF statements which are nested inside OP_ELSE conditional outcomes do not terminate the parent loop.

OP_IF, OP_NOTIF

OP_IF will execute the set of subsequent opcodes up-to the following OP_ELSE or OP_ENDIF if the value on top of the stack is True, or NON-ZERO. Similarly, OP_NOTIF will execute the set of subsequent opcodes up-to the following OP_ELSE or OP_ENDIF if the value on top of the stack is FALSE, or ZERO. If an OP_ELSE is the subsequent conditional clause and the first conditional clause was successful, the script will jump forward to the OP_ENDIF at the conditional-stack height of the original clause. the script will jump to the subsequent opcode following the else on a failure of the conditional entry. The loop concludes after an OP_ENDIF is processed.


OP_VERIF, OP_VERNOTIF

NOTE: OP_VERIF and OP_VERNOTIF are currently disabled in the BitcoinSV mining client and transactions that use them in executed script will fail

OP_VERIF will execute the set of subsequent opcodes up-to the following OP_ELSE or OP_ENDIF if the value on top of the stack matches the protocol VERSION. Some, or all network nodes may refuse to evaluate certain protocol versions meaning transactions using these parameters must be careful. Similarly, OP_VERNOTIF will execute the set of subsequent opcodes up-to the following OP_ELSE or OP_ENDIF if the value on top of the stack does not match the protocol VERSION indicated in the transaction serialisation string. Similarly to OP_IF/OP_NOTIF, ifan OP_ELSE is the subsequent conditional clause and the first conditional clause was successful, the script will jump forward to the OP_ENDIF at the conditional-stack height of the original clause. the script will jump to the subsequent opcode following the else on a failure of the conditional entry. The loop concludes after an OP_ENDIF is processed.

Example 1

The following example uses IF, ELSE and ENDIF statements to manage four possible ScriptSigs which can unlock this output.

   ScriptSig1:     <sig1> <pk1> 1
   ScriptSig2:     <sig2> <pk2> 2
   ScriptSig3:     <sig3> <pk3> 3
   ScriptSig4:     <sigRP> <pkRP>

The first three are PKH signatures with a numeric signal to show which conditional loop to enter for evaluation. Depending on which numeric signal is present, the script will enter the relevant height conditional clause. Each subsequent conditional IF statement is nested inside the else statement of the preceding level. If no numeric signal is present, the script goes into the third level else statement where the ScriptSig is tested against an R-Puzzle Hash and the script exits the loops.

   DUP 1 EQUAL IF
       DROP DUP HASH160 <PKH1> EQUALVERIFY CHECKSIG
   ELSE
       DUP 2 EQUAL IF
               DROP DUP HASH160 <PKH2> EQUALVERIFY CHECKSIG
       ELSE
           DUP 3 EQUAL IF
               DROP DUP HASH160 <PKH3> EQUALVERIFY CHECKSIG
           ELSE
               OVER 3 SPLIT SWAP DROP 1 SPLIT SWAP SPLIT DROP HASH160 <RPH> EQUALVERIFY CHECKSIG
           ENDIF
       ENDIF
   ENDIF

Example 2

In this example, three possible ScriptSigs are accomodated. The entry to the conditional clauses is based on the depth of the stack subsequent to the processing of the ScriptSig.

   ScriptSig1:     <SIG> <PK>
   ScriptSig2:     1 <SIG1> <SIG3> <SIG4>
   ScriptSig3:     <PASSWORD> <SIG6> <PK6>

Either of the first two ScriptSigs are evaluated in their own separate IF loops which exit using RETURN statements. If the ScriptSig has a stack depth that doesn't match either of the requirements, it passes through to a final evaluation which must have a different signature and a backup password.

   DEPTH 2 EQUAL IF
       DUP HASH160 EQUALVERIFY CHECKSIG RETURN
   ENDIF
   DEPTH 4 EQUAL IF
      <PK1> <PK2> <PK3> <PK4> <PK5> 5 CHECKMULTISIG RETURN
   ENDIF
   DUP HASH160 <PKH6> EQUALVERIFY CHECKSIGVERIFY SHA256 <PASSWORDHASH> EQUAL RETURN