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

Line 47: Line 47:
 
     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 which must contain a signature with specific parameters and a password.
+
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
Line 58: Line 58:
 
         FROMALTSTACK DUP HASH160 <PKH5> EQUALVERIFY 5 CHECKMULTISIG RETURN
 
         FROMALTSTACK DUP HASH160 <PKH5> EQUALVERIFY 5 CHECKMULTISIG RETURN
 
     ENDIF
 
     ENDIF
     OVER 3 SPLIT NIP 1 SPLIT DROP 27 LESSTHANOREQUAL VERIFY DUP
+
     DUP HASH160 <PKH6> EQUALVERIFY CHECKSIGVERIFY SHA256 <PASSWORDHASH> EQUAL RETURN
    HASH160 <PKH6> EQUALVERIFY SHA256 <PASSWORDHASH> EQUAL RETURN
 

Revision as of 01:15, 4 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

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. 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 <PK1> <PK2> <PK3> <PK4> <PK5>
   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 9 EQUAL IF
       TOALTSTACK TOALTSTACK TOALTSTACK TOALTSTACK 3 SWAP DUP HASH160 <PKH1>
       EQUALVERIFY FROMALTSTACK DUP HASH160 <PKH2> EQUALVERIFY FROMALTSTACK
       DUP HASH160 <PKH3> EQUALVERIFY FROMALTSTACK DUP HASH160 <PKH4> EQUALVERIFY
       FROMALTSTACK DUP HASH160 <PKH5> EQUALVERIFY 5 CHECKMULTISIG RETURN
   ENDIF
   DUP HASH160 <PKH6> EQUALVERIFY CHECKSIGVERIFY SHA256 <PASSWORDHASH> EQUAL RETURN