Flow-Control in Bitcoin Script.
We learned in previous articles, that the Bitcoin blockchain uses script, a scripting language used to add programmability of transactions and money in general on the blockchain. The script is a stack-based simple list of instructions that are recorded with each transaction describing how the recipient of bitcoins can access the coins. They allow users the flexibility of changing the spending parameters for sent bitcoins.
Unlike regular high-level programming languages such as Java, C++ and Python, Bitcoin scripts are theoretically and intentionally turing complete and lack a looping mechanism. They are also deterministic and by using scripts we are sure that the program will terminate at some point since infinite loops cannot happen. This feature keeps the system safe from cyber attacks such as DDoS attacks, infinite loops, and blocking among others. Although scripts lack looping functionalities, they support other programming language features such as bitwise operations, arithmetic, and constants among others.
In this article, we will focus on flow-control also referred to as conditional clauses and how they are implemented in Bitcoin scripts. Flow control in any programming language consists of if-then-else statements whereby for an action to be executed a condition must be met otherwise another action is performed.
Flow control in Bitcoin Scripts.
Conditional operational codes opcodes allow users to build redeem scripts that have two ways in which they can be unlocked. Of course, this depends on the outcome of a logical evaluation. For example, if TRUE a redeem script A is used otherwise if FALSE redeem script B is used. In addition to this, these expressions can also be nested whereby a condition is nested within another. Scripts provide for multiple execution paths since nesting is not limited. Note that although nesting is unlimited, there is a maximum size limit on the script.
In Bitcoin scripts opcodes such as IF, ELSE, ENDIF, and NOTIF are used to implement flow control. They can have boolean operators such as BOOLAND, BOOLOR, and NOT, which are just logical AND(&&/and), OR(||, or), and NOT(!/not) in other high-level programming languages such as Java or Python among others.
The following examples demonstrate flow control in regular high-level programming languages and Bitcoin scripts; High-level programming languages, Python, Java, C++;
if condition:
code if condition is TRUE
else:
code if condition is FALSE
code in either case.
Flow control in Bitcoin Script;
condition
IF
code if condition is TRUE
ELSE
code if condition is FALSE
ENDIF
code in either case
Notice how the condition that is being evaluated comes before the IF opcode, this also applies to other operations using the Bitcoin script. For example, a simple addition in python is written as follows, 1 + 1 while the same is written as follows in the script, 1 1 ADD.
VERIFY operational Codes(OP_CODES).
Bitcoin script also has conditional clauses that end in VERIFY meaning that if the condition being evaluated is FALSE, the script execution terminates immediately and a transaction is rendered invalid otherwise it the opposite happens. VERIFY, unlike the IF clause which can have multiple execution paths acts as a guard clause meaning that the script will only proceed with execution if a prespecified condition is met.
Consider the following example;
HASH160 <expected hash> EQUALVERIFY <A's Public-key> CHECKSIG
Above, a digital signature and a secret producing a hash from A are required for the script to unlock. For A to be able to redeem this, he/she constructs an unlocking script with a valid signature and pre-image;
<A's Signature> <hash pre-image>
We can also write the above using the IF clause as follows;
HASH160 <expected hash> EQUAL
IF
<A's Public-key> CHECKSIG
ENDIF
Between the two the former is considered more efficient even though they perform a similar task. Also, the opcode required for the former is less, which means that the transaction size will be smaller. Now, some situations require us to use the former(in the case of a precondition) while others require us to use the latter(multiple execution paths).
Controlling Flow of Execution in Bitcoin.
In most cases, flow control in Bitcoin is used to build redeem script that offers multiple execution paths, each path with a different way of redeeming a UTXO. Consider the following example, we have two signatories A and B. Remember what we learned about multi signatures. In this case, this is a 1-of-2 scheme. Meaning either one can redeem.
We specify this condition using an IF clause as follows:
IF
<A's Public-key> CHECKSIG
ELSE
<B's Public-key> CHECKSIG
ENDIF
Notice how the condition is not part of the redeem script. This is because it is specified in the unlocking script, this allows A and B to select an execution path as needed.
Participant A can redeem using the following unlocking script:
<A's Signature> 1
As in most programming languages, the number 1 is a TRUE value, in this case, the IF-clause executed the first redemption path for which A signed for.
On the other hand, B redeems as follows:
<B's Signature> 0
In this case, we used 0 which is a FALSE value, here the ELSE clause is executed.
If-clauses can be nested meaning we can construct redeem scripts with multiple execution paths each with a different method to redeem a UTXO. To be able to spend sent funds, we build an unlocking script that can navigate the execution path by placing appropriate TRUE and FALSE values on the stack at each point in the flow of control.
Summary
The guard clause is used in cases where we want execution only to proceed if a predetermined condition has been met. IF clause is used where we want to implement multiple nested execution paths. Nesting in Bitcoin Scripts is not limited however, the transaction size is limited.
References
Subscribe to my newsletter
Read articles from lumunge directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by