The Best Step-by-Step Bitcoin Script Guide Part 2


1 year ago
The Best Step-by-Step Bitcoin Script Guide Part 2

This is part 2 of our Best Bitcoin Script Guide. It is highly recommended that you read part 1 before you proceed with this.

The Best Bitcoin Script Guide Part 2

In part 1 we covered the following:

  • Introduction to Bitcoin Script.
  • How do transactions in Bitcoin work?
  • How Scripts work?
  • The game of locking and unlocking in scripts.
  • ECDSA cryptography in Bitcoin Script.

NOTE: From here on out, we won’t be using the “OP_” command as frequently because it should be understood that “OP_” will always be prefixed to each opcode. Please keep this in mind. We didn’t use “OP_” to enhance readability, when you are executing the script please remember to use “OP_”.

Multisignature Transactions

The transactions that we have seen up till now are all very simple (one-to-one in its nature). However, transactions can become much more complicated and layered than that.

First up, we will be checking out multi-signature transactions. In a multi-signature transaction, the only way that the bitcoin outputs can be unlocked is if multiple people verify the transaction.

So, where is this useful?

Imagine there is a huge multi-national company. Obviously, they won’t let one single person control all of its funds, right? They will have a board of people who will be in charge of the funds.

Now, how will that work in the context of bitcoin script transactions?

Multi-signature scripts set a condition where N public keys are recorded in the script and at least M of those must provide signatures to unlock the funds. This is also known as an M-of-N scheme, where N is the total number of keys and M is the least number of signatures required for validation. The transaction is also called M-of-N multisig.


The script format of a multisig output looks like this:




Let’s see how this works in an example.

Suppose we are sending money to a company headed by 3 people (Alice, Bob, and Charlie) and two out of those three people need to verify the transaction for it to go through. This transaction is also called a 2-of-3 multisig.

How will the output look like?




Alright, so this is the output. How will the company unlock the output and gain access to the funds? Remember that this is a 2-of-3 multisig meaning, 2 out of the 3 people involved must present their signatures.

So, the signature combination used can be any of the following:





Suppose Bob and Charlie are the ones verifying the transaction. The complete validation script will then read like this:




IF the conditions above hold true and the signatures are correct, then the ?


One of the most interesting aspects of programming is Flow Control. By using certain conditions one can detect which commands get executed and when. Anyone who has some programming base is familiar with the concept of IF-ELSE programming.

This is the simplest and most basic form of flow control.

In bitcoin script the following are used for state control:

  • IF


In a normal program, the IF-ELSE condition looks like this:


















So, what is happening here?

  • If the condition is True, then execute STATEMENT A.
  • Otherwise, execute STATEMENT B.
  • Afterward, STATEMENT C gets executed regardless of which condition one uses.

However, in bitcoin  script, it has a different look. Remember that the main feature of bitcoin script is that it is a stack-based language. That’s why in this case, the condition comes BEFORE the IF statement.

So, it looks something like this:
















What will the execution of this block of script look like?


Step 1: Condition gets popped on the stack:


Step 2: The IF opcode pops out of the Condition and checks if it is TRUE or not.


Step 3: IF true, STATEMENT A gets executed and the bitcoin script skips the ELSE statement to jump to ENDIF and push STATEMENT C onto the stack.


Step 4: If the IF opcode returns FALSE then the ELSE block gets executed and STATEMENT B gets pushed onto the stack.


Step 5: After STATEMENT B gets pushed onto the stack, the ENDIF condition gets activated and STATEMENT C proceeds to get pushed on the stack.



As we have seen before, flow control could be established via appending the VERIFY statement to certain conditions.




In this case, since 2 is not equal to 4, the script would stop executing then and there without even going to 3.


The Use of Flow Control in Bitcoin Script


One of the most common applications of Flow Control is to create redeem scripts which have multiple paths of execution.

We have already seen examples of multi-level executions with Multisignatures. Now let’s how the same multisig transactions can be written via Flow Control statements.

Suppose we are going to execute a 1-of-2 Multisig. The 2 people involved in the multisig are Alice and Bob and only of these two need to verify the transaction for it to go through.

So, for this multisig, how will the locking script be designed using flow controls?


Locking Bitcoin Script








As you can see, it is a simple straightforward if-else loop. However, there is something wrong here.

What do you think is missing?

That’s correct….the condition!

The Condition itself is missing… so is that an error? Really think about this right now… why didn’t we put the condition in the Locking Script?

Having a condition will unlock the IF-ELSE script and let you access the statements, WITHOUT providing a verification. Remember, the IF-ELSE script can only be unlocked if certain conditions are met.

This is why, in the locking script we provide the IF-ELSE code without the condition.


Unlocking  Bitcoin Script


In the unlocking script, Bob or Alice provide their signature and the conditions required to unlock the script.

According to the script, Alice’s code gets unlocked if the condition is TRUE and Bob’s code gets unlocked if the condition is FALSE. We use “1” to signify TRUE and “0” to signify FALSE.

So, keeping all this info in mind, Alice’s unlocking script would be:




Bob’s unlocking script is:




Script Execution


Suppose Bob wants to unlock the UTXO, this is how the combined validation script would look like (we are going to use in this example instead of the whole IF-ELSE code to enhance understanding):




Step 1: Bob’s Signature will get pushed on the stack.

The Best Bitcoin Script Guide Part 2

Step 3: Now the fun part begins.


It is time for the to get executed which happens to look like this:








First, the IF condition pops “0” out of the stack.

The Best Bitcoin Script Guide Part 2

Step 5: CHECKSIG gets executed which pop’s both the Signature and Public Key from the stack and runs the CHECKSIG operation on them.

Alright, so this was a simple 1-of-2 multisig.

However, let’s up the ante a bit more and see what happens when we increase the Flow Control in a script.










Alright, so we have three statements that we want to execute. In order to execute a particular statement, we will need to input certain conditions to reach them.

To execute STATEMENT B, what conditions need to be input? The conditions will be: 1, 0 OR {TRUE, FALSE}.

But wait, Statement B, comes after one ELSE and one IF right? So shouldn’t the condition sequence be 0,1 OR {FALSE, TRUE}?

Well… remember that Script is a Stack-based programming language. So, an input of {TRUE, FALSE} would appear like this on the stack:

The Best Bitcoin Script Guide Part 2

So, what’s the first thing that will get popped out?

FALSE right?

This FALSE condition will make the script skip IF and jump right to ELSE.

That’s why whenever we need to put in the conditions, remember the way a stack works.

What is Timelock?


A timelock is a primitive smart contract that levies time-based restrictions on Bitcoin spending. The three timelocks used in Bitcoin:

  • Transaction Locktime (nLocktime).



“nLocktime” is basically the parameter which defines the time before which the transaction couldn’t be accepted into the block. Every transaction set includes the nLocktime. There are three possible routes that nLocktime can take:

  • If nLocktime is set to 0 then the transaction is propagated immediately.


  • If 0


  • If nLocktime> 500 million, then it is interpreted as a Unix Epoch timestamp and the transaction isn’t valid until the specified time has passed.

While nLocktime looks good on paper, there is a very glaring weakness.

Suppose Alice wants to send Bob some BTC with a locktime of 1 week. There is a possibility that Alice can use the same UTXOs to create another transaction before the 1 week has elapsed with 0 locktime.

So, the receiver is completely dependent on the ethics of the sender.



The problem with the nLocktime was that the time locking was applied to the transaction which made it vulnerable to malicious users. So, CLTV or CHECKLOCKTIMEVERIFY made the locking applicable on individual outputs. So, to put it in simple terms, CLTV made the individual outputs of a transaction accountable to time locking.

CLTV has been implemented in a primitive off-chain payment channel which gives resistance against possible malleability. CLTV-Style Payment channels were implemented post BIP 65. Let’s see how it works:

  • Alice (The Merchant) gives her public key to Bob (the customer).


  • Bob uses his public key and Alice’s to make a P2SH address using the following conditions:Condition 1: Both Alice and Bob sign on any transaction that happens through this address.Condition 2: Only Bob can sign of any transaction on his own but that transaction must have a locktime greater than the refund deposit.


  • Bob immediately creates a deposit transaction and broadcasts it on the blockchain. Because of condition 2 above, he is assured of the fact that he can pretty much generate a refund on demand.


  • Now, remember, the first condition states that the Alice and Bob both need to sign on any transaction that happens in the P2SH address. So, Bob (the customer) can sign his part of the transaction and Alice can sign her part without revealing her signature details to Bob. By doing this Alice can broadcast the final payment to the blockchain before the refund can get broadcasted.




Before we understand how CHECKSEQUENCEVERIFY or CSV works, you need to know the difference between absolute timelock and relative timelock.

While nLocktime and CLTV are absolute timelocks, meaning they specifically mention an absolute point in time, relative timelocks specify an elapsed time from the confirmation of the output in the blockchain.

CSV or CHECKSEQUENCEVERIFY is a relative timelock. The CSV opcode specifies an “nSequence” variable.

The CSV opcode, when called, will stop the script from executing unless the nSequence indicates that an equal or greater amount of relative locktime has passed than the one mentioned in the CSV opcode.

Alright, so let’s have some fun now. Let’s utilize a script using flow control and CSV!

Imagine we have a company owned by 3 people: B, C, and D. The company runs on a 2-of-3 Multisig meaning, the funds of the company can only be used if at least 2 out of the 3 people present their keys.

However, in case of the people end up losing their keys, they need to make a fail-safe to make sure that the funds can still be activated by 2-of-3 Multisig. In this case, they make a backup key and give to their lawyer A.

So, how will that look in the script?








<B's Pubkey> s Pubkey> <D's Pubkey> 3 CHECKMULTISIG




As you can see, there are three ways that the flow can go:

  • If everything is well and good, then it acts like a simple 2-of-3 multisig.
  • If one of the owners loses their key and can’t produce it in 30 days, then the conditions required to get access to the funds are the lawyer’s key AND a 1-of-3 multisig with the 3 owners.
  • If all 3 owners lose their keys, then the lawyer gets to access the funds after 90 days.


Condition #1: Everything is Good

If everything is good and nobody has lost any keys, then 2 of the 3 owners will verify the transactions with their signatures like in any normal multisig.


Unlocking Script: 0


Note: Don’t forget that all multisig transactions begin with a “0” to workaround the CHECKMULTISIG bug.

Complete Validation script: 0


So, how does the execution looks like?

Step #1: The Unlocking script gets pushed on to the stack step-by-step

The Best Bitcoin Script Guide Part 2

Does that look familiar?

Yup…that’s the 2-of-3 multisig and the bitcoin script gets executed normally.

Condition #2: One person loses their keys

In this case, the lawyer A comes into play.


Unlocking Script: 0


Complete Validation script: 0


So, how does the execution looks like?

Step #1: The unlocking script gets pushed on to the stack.

The Best Bitcoin Script Guide Part 2

Step #3: The upcoming sequences are:




The “<30 days> CHECKSEQUENCEVERIFY DROP” basically activates a timelock of 30 days. If within the timelock the owner who lost their key can’t retrieve it then the script moves on to the next element in the stack.

However, if they can retrieve the key and show proof, the script immediate stops executing (since the VERIFY code is appended).

Note: So what is DROP? Suppose the parameter needed to satisfy CHECKSEQUENCEVERIFY is submitted, the time parameter that preceded it i.e. “<30 days>” is still on the stack. The DROP function pops the last item on the stack which happens to be, in this case, <30 days>.

The Best Bitcoin Script Guide Part 2

Now, this becomes a 1-of-3 multisig. If B’s signature checks out then the script executes properly.

Condition #3: All three owners misplace their keys


In this case, the Script won’t even execute the first IF, it will jump straight to the ELSE statement.


Unlocking Script:

Complete Validation script:


So, how does the execution looks like?

Step #1: The unlocking script gets pushed onto the stack.

The Best Bitcoin Script Guide Part 2


The aim of this guide was to make you understand the logic behind various Bitcoin Script transaction scenarios. It is intriguing to see the mechanism behind these transactions, to say the least. If you haven’t read part 1 of the Bitcoin Script Guide  be sure to check it out!

Like what you read? Give us one like or share it to your friends

';return t.replace("ID",e)+a}function lazyLoadYoutubeIframe(){var e=document.createElement("iframe"),t="";t+=0===this.dataset.query.length?'':'&'+this.dataset.query;e.setAttribute("src",t.replace("ID",,e.setAttribute("frameborder","0"),e.setAttribute("allowfullscreen","1"),this.parentNode.replaceChild(e,this)}document.addEventListener("DOMContentLoaded",function(){var e,t,a=document.getElementsByClassName("rll-youtube-player");for(t=0;t