Bitcoin Script Explained

By
Allan Kershaw
December 28, 2024
20
min read

Before we begin our descent into an explanation of Bitcoin script, it is helpful to remember that Bitcoin is designed to work the same way that cash does. I want something from John, so I pay John for his services rendered with a currency we have both agreed upon. But with bitcoin, John could be in Hong Kong, while I am in Montreal. I will also not likely have John’s name, but instead his address or wallet where I will send the Bitcoin transaction.

The major difference between Bitcoin and traditional currencies is that not only is Bitcoin not a physical coin. Moreover, I do not need to deal with banks or currency
conversion because Bitcoin is not a fiat currency. Instead, Bitcoin is a decentralized cryptographic currency that is shared on multiple networks. Because its foundation
relies on blockchain, every time coins are sent, or more correctly, a transaction is made, an immutable record of the exchange is made.

When it comes to the contents of a transaction, Bitcoin script is a fairly basic programming language and computational processes. But if you are new to the crypto world it is a little bit tricky as there are many important concepts that need to be unpacked.

So settle in, and let’s go through some of the basic concepts you need to know in order to understand what Bitcoin Scripting is and how it works.

The way this article works is from a basic description of Bitcoin script to a much more detailed description, ending with some basic opcodes examples. I also continue to
repeat concepts as we learn about them and add them to our arsenal, so we get more comfortable with them as we go along.

  1. Transactions Basics
  2. Programming Language and SHA-256
  3. Looking at Cryptographic Details of Bitcoin Script
  4. Operation Codes and Script in Detailed Diagrams
  5. Article Overview and Conclusion

There are five sections in this article. Each section in this article is written as a self-contained Bitcoin Script explanation. However, if you want to know more, just keep reading the following section as each is increasingly detailed. The funct section Operation Codes and Script in Detailed Diagrams, is the least beginner friendly. But if you
just want to know what some of the central opcodes are, then head on over!

Here is the outline of this article. The topics begin with the most basic, and progress to the more complex:

Complete Article Outline

  1. Transaction Basics
  2. Programming Language and Script 
  • The Qualities of Bitcoin Script:
  1. A Closer Look at the Cryptographic Details of Bitcoin Script 
  • Public v. Private Keys and Digital Signatures 
  • Characteristics of A Bitcoin Address: 
  • Transaction Verification: 
  • ScriptSig: Input and Output 
  • Elliptical Curve Function and Signature Verification 
  • Bitcoin Transaction Message: 
  • Valid transactions: 
  • Consensus Protocol 
  • Serialization of Transactions:
  • Signatures and multisig
  1. Operation Codes and Script in Detail
  • The basic features of Bitcoin Script are the following:
  • Forth-like programming language:
  • Linear Data Structures and “push” and “pop” functions
  • Opcodes
  • Multisignature Transactions
  • Pay-to-Script-Hash or P2SH
  • Flow Control
  • Locking and Unlocking Script
  • Locktime
  1. Article Overview and Conclusion
  • Programming Language
  • SHA-256 and hash functions
  • Private Key
  • Public Key
  • Signature
  • Hashing Functions and SHA-256
  • Cryptographic Details of Bitcoin Script
  • Transaction Verification
  • Elliptical Curve Function
  • Bitcoin Transaction Message
  • Valid transactions
  • Transaction Fees (Miner’s Fees)
  • Consensus Protocol
  • Serialization of Transactions
  • Signatures and multi-sig
  • Forth-like programming language
  • push and pop function
  • Linear Data Structure
  • Opcodes basics

So, if all you want to know is the basic structure of the script of a Bitcoin transaction; then you can stop after the first section. If you would like to know more about the
nuances of Bitcoin script then stay with me and keep reading.

I also need to give a special mention and thanks to Andreas Antonopoulos and Jimmy Song for their helpful and detailed descriptions of Bitcoin Script.

This article is not as technical as Andreas’ talks nor as comprehensive as Song’s book. Instead, it is a much more basic description for a broader audience. There is not
detailed enough information here for the reader to learn how to code bitcoin. Nevertheless, you should feel pretty comfortable with the fundamentals of Bitcoin Script
by the time we are done.

Cryptography

The cryptographic transactions exchanged as a monetary currency is the essence and value of Bitcoin. To understand exactly how these transactions transpire, you need to understand what Bitcoin Scripting is; which is exactly what I am going to explain here.

Because Bitcoin is not a physical currency, you cannot spend them the same way you would physical cash even though, like cash, transactions are peer-to-peer. Although Bitcoin is not a physical currency, you might think of bitcoin transactions as being similar to the way that writing a personal cheque works. When I write a cheque, on that piece of paper is my account number, the amount I am giving the recipient, the name of the recipient, and my signature endorses the transfer of funds from my account.

So when the recipient takes that piece of paper to a bank teller (or more likely an ATM), she signs the back of the cheque to prove that she is the correct recipient. Once all of these steps are complete, the bank knows to move money from my account into that of the recipient.

In some sense, Bitcoin transactions have many things in common with the OG personal cheque. Bitcoin script relies on account numbers (called addresses), signatures and verification processes. But instead of relying on a bank, Bitcoin relies on the public blockchain ledger. Miners check that the amount leaving my account is available, and approve the transaction via cryptographic hashing; so this is where things get tricky and my analogy to paper cheques falls apart.

Cryptography is central to the function, value, and security of Bitcoin and other cryptocurrencies. The word cryptography comes from the Ancient Greek κρυπτỏσ γράφειν which is the combination of the word kryptos, which means “secret” or “hidden,” and the verb graphein, “to write.”

Modern cryptography relies on the same desire for secrecy and coded language of the ancient world, and without the necessary tools and information, it is not possible to correctly solve the code.

Cryptocurrencies like Bitcoin, complicated mathematical algorithms to encrypt individual addresses and private information; most notably the double hash function SHA-256.

This article covers the following concepts in an effort to explain the method behind the Bitcoin transaction process; or more correctly Bitcoin scripting language.

One: Transaction Basics

For starters, in order to send and receive Bitcoin (which are cryptographic transactions), you need a “digital wallet” which is a collection of private keys. A wallet is necessary to store relevant information, such as the keypairs, used for transactions, as well as past transactions from one’s account.

The keypairs amount to a proof of ownership (or keys) and an account balance (of UTXOs) which are available for exchange in one’s wallet.

Bitcoin, like emails, are be sent and received via addresses. When you want to complete a transaction with someone, you must share your address with them. However, unlike an email account, you have many different Bitcoin addresses. Each transaction needs a unique public and private key.

Here is what the basics of a Bitcoin transaction looks like:

Alice (A) wants to send Bob (B) Bitcoin. In order to do so, she must create a message with details like “send Bob 5 Bitcoin.” The message from Alice gets hashed. Then, that hash is the cryptographic signature that is sent to Bob.

A and B must then prove they are the owners of their respective addresses and in possession of both private and public keys. The digital signatures of A and B are then
verified by Bitcoin miners. Once the signatures are verified as matching the transaction is verified and Bob has new UTXOs.

NOTE: A Bitcoin message does not look like a typical word message. It will look something like this.

EXAMPLE:
Private Key: KxeNcRw8mBfyLrnnXQymQkogLjvmn6uJCmSWLRmZ6Mt3Hzfgo1mY
Deposit Address: 1MnU3iyTeej69DKGGKo6vU3H3dKKZ9ZL6u

Once the transaction between Alice and Bob has been verified by miners it also becomes part of the immutable Bitcoin blockchain. Within each recorded block are the
details of the transaction between A and B as well, the information of previous Bitcoin transactions.

As I mentioned at the start, Bitcoin is not a physical coin, but a history of cryptographic
transactions. The history of the transactions and its exchanges are a part of the security
and value of Bitcoin. So, understanding Bitcoin script is the essence of the value of
Bitcoin transactions.

As I mentioned at the start, Bitcoin is not a physical coin, but a history of cryptographic transactions. The history of the transactions and its exchanges are a part of the security and value of Bitcoin. So, understanding Bitcoin script is the essence of the value of Bitcoin transactions.

Keep reading if you are still interested in Bitcoin script, and if you want to know more about how the script works.

In this next section I will discus the following topics:

  • The Qualities of Bitcoin Script
  • The difference between Public and private keys
  • Cryptography and in Bitcoin’s Script
  • The design of Elliptical Curve Functions and why reverse engineering a hash is infeasible

Two: Programming Language and Script

If you thought the above explanation was a bit too simplistic, well, you’d be right. Here is a slightly more detailed description of the processes of a Bitcoin Transaction.

What goes on in order for B to receive A’s Bitcoin transaction is computationally very difficult. The difficulty of these computations is such that all of them are done with
specified computers and programs.

So although one can have a Bitcoin wallet using a personal computer, Bitcoin transactions are mined with much more computationally robust computers. Presently,
mining Bitcoin transactions use an incredible amount of computational power and therefore is very costly, so the majority of mining goes on in mining pools.

The cryptographic algorithms that Bitcoin uses depend on a design that makes hashes reasonably easy to compute and very inefficient to reverse. This is known as the
computational hardness assumption. This assumption trades on the ideal state in which adversaries are computationally limited. As a consequence of the computational energy required and the time it takes to perform this, adversaries are not likely able to reverse the computation, (which is the case most of the time).

Basically, Bitcoin Script is programmable money. Bitcoins are not physical coins. Instead, bitcoin is a history of signatures that are cryptographically secure. To own bitcoin is to have in your possession a complete history of the transactions. Ownership includes a pair of keys that enable you to keep track of and use your bitcoin; a shared public key, and a private key that is not.

The design of Bitcoin script is to provide flexible parameters necessary to perform a transfer. Bitcoin’s creator Satoshi Nakamoto disabled many functions in the program.
Multiplication is one of the disabled functions, which keeps the script simple in terms of programming.

Bitcoin uses a small set of simple templates to perform digital signature verification. All operations are a pure function of the machine state, which means that there is no
interference from external operations acting upon the inputs of a transaction script.

Bitcoin uses a built-in programming language which determines if a transaction can be authorized to transfer funds. The design guards the funds. The coins are only
redeemable with a digital signature with an input that returns the program successfully. This constitutes a valid transaction. Once that is complete, the bitcoin are transferred from one address to another.

What does it mean to say “the transaction is sent to an address?”

The Qualities of Bitcoin Script

Bitcoin script is a forth-like, stack-based, reverse-polish, Turing-Incomplete programming language, and uses a stack-based minimalist program. Minimal program
requirements and limitations is a necessary part of the functional design of the cryptocurrency.

Forth-like is a programming language similar to “stack-based” language. One of the intentional limitations is that the programming language is Turing-Incomplete (that is, it is NOT Turing-Complete). Incompleteness prevents the program from infinite loops occurring.

Bitcoin programming language relies on a linear execution of operations. Linear, means that one direction is executed after the other consecutively. Therefore, the operations are executed from left to right; which is referred to as “last in first out.

Reverse-polish refers to the use of operators, like “+/*” (addition or multiplication). For Bitcoin code, the operators follow the variables, more on this a little later.

Bitcoin uses “static analysis” which dictates the general parameters of the program and setting computationally reasonable limitations. This is to ensure that the program is easy enough to allow checking the bounds of other users’ smart-contracts.

Bitcoin script is also Turing-Incomplete. Turing-Complete means that if a machine had enough memory and computational power any computation could be solved. This
means that completeness operates with endless loops of code in order to solve the computation.

Turing-Incomplete does not make infinite loops. Loops are useful when building programs.

However, there are several reasons that Bitcoin script does not loop, this is an important feature for program execution, and avoiding bugs.

Hypothetically, anyone can create a scripting program that every full node on the network executes. If Bitcoin Script were Turing complete, it would be possible to have
infinite loops, and the program would execute without end. This means validating nodes would enter and never leave that loop. This would create an easy way to attack the network through what would be called a denial-of-service (DoS) attack. A single Script program with an infinite loop could take down Bitcoin. The system is protected against these vulnerabilities because is uses a Turing Incomplete program.

Alternatively, Ethereum, which has Turing completeness in its smart contract language, Solidity, handles this problem by forcing contracts to pay for program execution with something called “gas.” So in the case of an infinite loop, once the gas has been exhausted it will stop. However, by definition, it will run an infinite number of times.

Another reason to avoid Turing completeness is that smart contracts with Turing completeness are very difficult to analyze. A Turing-complete smart contract’s execution
conditions are very difficult to enumerate. With a complete system, it is easy to create unintended behavior, causing bugs. Bugs in a smart contract make coins vulnerable to unintentional spending.

These bugs posed a serious problem in the DAO (Decentralized Autonomous Organization). It was a Turing-complete smart contract that resulted in the Ethereum Classic hard fork, which means a new coin was created.

As a result, Bitcoin script avoids the unnecessarily use of complicated transactions, rather they must be relatively easy to compute. Continuous loops would require too much computational power and slow the networks, which would go through the hash-rate of SHA-256 too quickly.

Three: A Closer Look at the Cryptographic Details of Bitcoin Script

The Holy Trinity of the Cryptographic Bitcoin Address:

  1. A private key
  2. A public key – derived from the hash of the private key
  3. An address – derived from the hash of the public key

The following is a QR code: 1JMqyd22x3ZFsdX8zXcbPfwKf72S6BTbtH

From the 1 to the H is a valid bitcoin address. Anyone can send Bitcoin to the address and the holder(s) of the private key associated with the address will be able to transact them.

The process is one way, as reversing the scheme is intractable. Aside from the random method of brute-force, it is not possible to derive a public key from a bitcoin address. Just so, one cannot derive a private key from a public key.

Public v. Private Keys and Digital Signatures

Private key:

A Bitcoin private key is a single unsigned 256-bit integer made of 32 bytes. A private key is secret, as indicated by its name. only an owner knows her private key. Private keys are a sequence of randomly generated numbers. For Bitcoin transactions, to unlock and spend a transaction, the sender must have the corresponding private key on the blockchain so that she can spend the funds.

Public key:

A public key can be calculated from a private key, but not vice versa, this is because of the design of the hash function, which relies on the elliptical curve function (which will be discussed later on in this article). The public key is public, while the private key that corresponds to it is not.

Bitcoin public keys are either compressed or uncompressed. Compressed public keys are 33 bytes, with the prefix of “0x02” or “0x03”, and a 256-bit integer. (Uncompressed keys are the older formally used public keys). Keys are 65 bytes called x, with the prefix, “0x04”, followed by two 256-bit integers called x and y (2 * 32 bytes).

Signatures:

A cryptographically generated alphanumeric sequence is produced to prove the operation occurred. A signature is generated with a combination of the hash of a transaction that needs to be signed and the hash of a private key.

Signatures are typically either 73, 72, or 71 bytes long, although sizes even smaller than that are possible with decreasing probability.

Characteristics of A Bitcoin Address:

Bitcoin addresses are 34 characters long. This is generally the case. They can theoretically be as short as 26 characters if the public key that generates them starts with a series of leading zeros. Again, you cannot go backward in the scheme, so if you wanted a shorter bitcoin address you would have to first start guessing at private keys
that produced public keys with leading zeros, which would then lead to a bitcoin address that was shorter than 34 characters. There are bitcoin address generators that
perform this process at a computational expense.

Bitcoin addresses are made up of the following three parts: A version number (1 byte), a public key hash (20 bytes), and a checksum (4 bytes). The ‘1’ at the beginning of the example addresses represent the version number. They are typically 34 characters long, however they can be shorter if the public key from which they are derived begins with a series of zeros.

Bitcoin transactions are a process of cryptographically signed records. Ownership is transferred by sending these transactions from one wallet (or Bitcoin address) to
another. Each digital transactions has requisite inputs, in turn, the desired output is ensured. In the case of a Bitcoin transaction, the desired output is new UTXOs for Bob.

To participate in transactions the users must each have an address and two kinds of keys: public keys and private keys. Alphanumeric characters make up each key. Only the owner of the private key has this information. But Alice shares her public key is with Bob, and both addresses are publicly available.

Public Keys are available for all to see, they are all available on the public ledger. The public ledger shows an address’ account balance, as well as the history of all of its
transactions and the information, is shared publicly. This allows others to see a record of all transactions from said address. More importantly, an address is required to send and receive Bitcoin transactions.

When making a transaction, Alice and Bob share their public keys, but they never share their private keys. A private key, also known as a digital ID, is necessary for a script to be valid. It is also necessary that the transactions are completed within the parameters of the initial message. As mentioned, private keys are cryptographically secured hash functions. The miners must, therefore, solve the computation to ensure that the private keys match the details of the transaction.

Roughly, the transaction looks something like this:

Alice: 256 bit passphrase — private key — hash 256 — RIPEMD160 — hashed (twice) — match to private keys

Bob: private key — [hashed] — public key — [hashed again] = address

Miners compete to confirm the transaction for the win of the transaction fees and the creation of and until 2040 when Bitcoins can no longer be mined the creation of new Bitcoins. Once a transaction has been verified by the miners, a block is added to the blockchain. Each block contains some or all of the transaction that is being verified. The transaction is verified when the sequence with the most proof of work is declared.

Before a transaction is broadcast to the decentralized Bitcoin network, it must be digitally signed by the current owner with the private key. The public key is hashed from the private key, and then the private key confirms ownership of the corresponding public address.

So, Alice sends a transaction to Bob with the pay to public key hash script (P2PKHS).

Operations are added to the stack and then processed linearly from left to right.

Example:

  1. DUP_HASH160 <BobPkH> EQUAL
  • <BobPkH> is preserved and encrypted behind the double hash function, first hashed through SHA 256, and then RIPEMD160. A 160-bit sequence is returned to the stack and will need to match Bob’s Public Key in the signature in the next operation.
  1. <BobSig><BobPubSig>
  • Bob’s digital signature and public key are confirmed in sequence before they are verified.

VERIFY:

VERIFY is a variable that is written into the unlocking script. VERIFY is a Guard Clause and is also functions as Flow Control. One does not need to add VERIFY to the sequence of opcodes. This is an opcode in the middle of a script that works to ensure that certain parameters are met throughout the sequence. this is a safeguard so that the script does not just rely on the automatic verification that occurs at the end of a script. If the conditions are not verified, then the code will not continue to execute itself. So, if in the middle of a script the conditions are not met, then the code will halt and stop running.

Say that Alice wants to provide conditions under which Bob receives his Bitcoin. The same way it is possible to add another signature to the script, verify can be added to the sequence of opcodes.

All Bitcoin transactions are self-contained, so while the transaction itself is immutable, the ownership of transactions is malleable. This is because individual transactions do not depend on a global state of the blockchain. Transactions are designed so that ownership is passed from one address to the next.

Transaction Verification

You might still be wondering: How is a cryptographic signature made? And how do Bitcoin miners approve transactions?

Bitcoin’s script uses cryptographically generated public keys and private keys. This means that addresses are created using one-way mathematical functions. One-way
mathematical functions function that the input is easily computed, while the inversion of the function is infeasible by virtue of its computational difficulty. Basically, in order to solve for the original hash, one would have to use the random brute-force method, and this is extremely computationally slow and expensive.

Bitcoin script has married the ideals of transparency and security using the SHA-256 cryptographic hash function.

Bitcoin transactions and wallets are publicly available. Just to go the Blockchain Explorer, and you can observe a multitude of transactions transpiring on Bitcoin’s blockchain, along with other cryptocurrencies as well.

Now below is an illustration of the message and cryptography that allows Bob to receive 5 Bitcoin from Alice.

The following is an actual example of what a random transaction of Bitcoin looks like after the inputs and output have been cryptographically hashed.

ScriptSig: Input and Output

Input Script:

02473044022056e615f489f80887760517c15e50a5667c0fa4e39b89e52dd222779e3bb81a0d022029379f49226d407c166eea7cab69a85423d038de88e6997e1bcdd9dfbAb50121029403fb4f07e211c143ae26f9300b1de2ab1e763d28ec305365b3a09a3b678fO
utput Scripts

Output Script:

02473044022056e615f489f80887760517c15e50a5667c0fa4e39b89e52dd222779e3bb81a0d022029379f49226d407c166eea7cab69a85423d038de88e6997e1bcdd9dfb274e
Ab50121029403fb4f07e211c143ae26f9300b1de2ab1e763d28ec305365b3a09a3b678fOutput Scripts

This is because of the Bitcoin secret sauce (or not so secret), the double hash function SHA-256.

SHA-256 is Bitcoin’s cryptographically secure hash function. This hash function is used because it is deterministic, collision resistant and is relatively fast to compute, as well as infeasible to reverse.

The SHA-256 function, which is crucial to the script and cryptography of Bitcoin, uses a limited set of processing functions and only 11 variables. Allowing only limited functions within the script is a function of Bitcoin’s secure script and encryption.

First, the public key is hashed using SHA-256 to create a 256-bit output hash. The resultant hash is then run through RIPEMD-160. RIPEMD-160 produces a 160-bit output hash. Thus the final output is a 160-bit hash.

Elliptical Curve Function Signature Verification

In order to know how the operation CHECKSIG works, you need to understand what a digital signature is. A digital signature is a cryptographically generated code. The
signature is then authenticated by public key encryption. Essentially, this means that the keys need to match in order for the operation to continue.

The digital signature algorithm used by Bitcoin is the Elliptical Curve Digital Signature Algorithm or ECDSA. Essentially this is the main ingredient in the SHA-256 secret sauce.

Bitcoin uses elliptical curve cryptography (as well as Ethereum, among other cryptocurrencies), as the foundation of their encryption processes.

An elliptical curve is a function that satisfies the following equation:

Y^2 = x^3 + ax + b

This is an incredibly complicated mathematical formula. So to avoid error, I will not say too much more about the nuances of the function.

The qualities of an elliptic curve are:

  • The curve is symmetric across the x-axis
  • Any line that goes through 2 points on the curve will intersect the curve on a third point
  • Any tangent on the curve will intersect the curve on one more point

One of the main features of this function is that while it is easy enough to compute, it is very difficult to reverse engineer. This is why it is appealing; it is nearly impossible to solve for from the outcome. In order to solve backward would require an unfeasible amount of time and computational power.

This is as detailed as I will get regarding Elliptical Curve Functions. Its application is central to the creation and security of the cryptographic signature. If you want to know more about the specific parameters and outcomes of the formula, there is a plethora of information available for your perusal.

Bitcoin Transaction Message

Bitcoin transactions contain 3 distinct and important parts: input, the amount of bitcoin sent (which may mean a collection of transactions) and the output.

Every confirmed transaction results in the removal of spent coins from UTXO the database.

UTXO, or “Unspent Output from Bitcoin transactions” is a descriptive name for the input of the next transaction. That is, the input is hashed and becomes output, and that output becomes the input of the next transaction with the Bitcoin.

As depicted below, transactions can be combined, or rather UTXOs are combined. The vout then distinguishes different transactions from one another.

If a transaction has two UTXOs the first one will be labeled “0” and the second one will be labeled “1”.

The input explains the history as well as the current ownership of the transaction. Therefore, the input expresses the initial state of the program. It is also an aggregate of
previous transactions outputs. Because the input is the output of the previous transaction, the public ledger and the transaction records indicate how all Bitcoin
transactions came to be in the ownership of a specific address.

The sum of all inputs must be equal to or greater than the sum of all outputs. A transaction will likely include a collection of transactions. If the input exceeds the output
this remainder is used as a transaction fee. Transaction fees are redeemable by the first miner to include the transaction in the chain.

Input 2 – 0.25 BTC – for Bob
Input 3 – 0.25 BTC – for Bob
Input 4 – 0.25 BTC – Transaction Fees

Taking into account the transaction fee of 0.25 BTC, the output of the transaction is the amount of bitcoins that Bob will actually receive.

That looks look like this:

Output 1 – 0.25 BTC
Output 2 – 0.25 BTC
Output 3 – 0.25 BTC
Output 4 – 0.25 BTC

For example, if a user sends 2 bitcoins in a transaction, but they have a UTXO of 10 bitcoin, the entire 10 bitcoins are sent. Then the output produces a new UTXO of the
remainder from 10:

Output 1 – 2 BTC payment to the recipient
Output 2 – 8 BTC payment back to the user’s wallet as change

But realistically, this is more what these cryptographic transactions look like:

Bitcoin’s script cannot run successfully without the correct input. The program specifies a public key which needs to be validated by a digital signature. That means that the corresponding private key must create a valid cryptographic signature when hashed.

Valid transactions

Bitcoin’s design uses a code that runs on a network that checks the validity of the blocks being added to the blockchain.

A transaction is valid if the hash of the program matches the hash of the output being redeemed. Only when the item at the top of the stack is TRUE is the transaction valid. A transaction is FALSE when if it is a zero or negative zero.

The transfer is successfully executed with a TRUE value on top of the stack. That means if all of the operation codes are satisfied, and the addresses and keys also match, then the transaction is approved, and added to the blockchain.

Transaction Fees or Miner’s Fees

Each transaction comes includes mining fees. This is the fee that Bitcoin miners require for mining or approving transactions. The spender is typically responsible for the fee and the fees vary depending on the rules of supply and demand, so fees will rise and fall depending on consumer demand.

Miners receive the data of the transaction via the decentralized network. Multiple miners then compete to verify the transaction by solving the complex mathematical
problem of the hash. a new signature is created when the computation is solved. The signature then becomes part of the newly updated transaction history.

Each transaction included as a block in the blockchain has the history of the previous transaction. That means that included in every block is the original input, the hash of the input, and the new output.

Consensus Protocol

The process of transaction approval is part of the Consensus Protocol or “Nakamoto” consensus.

Consensus protocol uses the public ledger to store the complete list of transactions that have taken place in the history of the bitcoin network. A cryptographic chain of blocks that have been computationally created, is what maintains the security of the blockchain.

Consensus demands that the network agrees to the rules or design of the programming language to verify all new blocks and transactions. That means that the data in the blockchain must be consistent across all miners.

All transactions are deemed valid based on the most current state of the blockchain. This is the process of preventing the double spend problem. Thus if a transaction has already been added to the block, it cannot be spent again. Even if the sender has sent it to two different addresses, only the first approved transaction is reflected in the state of the blockchain.

Serialization of Transaction

Serialization is the process of converting a Bitcoin transaction into a hexadecimal sentence. Serialization is also known as a “byte stream”. This is the process of converting the internal representation of the data structure into a format that can be transmitted one byte at a time. This is necessary to manage the size and amount of data in a transaction.

Output Serialization Parts

8 bytes Bitcoin | value: 10^-8
1-9 bytes (VarInt) | Locking-Script length in bytes to follow
Variable | A script that defines the conditions necessary to spend the output

Input Serialization

32 bytes | Transaction Hash: Pointer to the transaction with the UTXO
4 bytes | Output Index: index of the UTXOs (the first index is “0”)
1-9 bytes (VarInt) | Unlocking Script Size: byte size
Variable |Unlocking Script: fulfills conditions of the UTXO locking script
4 bytes | Used for locktime or disabled (0xFFFFFFF)

Again, if you want to learn more about coding Bitcoin, please follow up with Jimmy Song’s book on Python language and programming.

Signatures and multisig

Cryptographic signatures, or signatures, provide proof of ownership of the private key that corresponds with the public key.

Some transactions have a script that requires multiple signatures. Multisignature means the transaction requires more than one key for authorization. Multiple signatures are generally used to divide the responsibility of the possession of some shared Bitcoin. This can be done for many reasons, be it that it is a shared account or a business account that requires multiple stages of approval. However standard transactions are single transactions.

These transactions rely on complicated scripts because the transaction is larger than a typical peer-to-peer transaction. There may be an instance where 5 signatures are needed because there are 5 partners involved in the transaction.

Multisig transactions use the formula M-of-N.

  • N is the total number of keys
  • M is the least number of signatures required for validation of the transaction

Operation Codes and Script in Detail

In this section, we will get more detail on opcodes and script, and look at a few of the operation codes that are actually part of the Bitcoin Script.

The basic features of Bitcoin Script are the following:

  • Stack Based is much like Forth-like language with is also stack-based.
  • Forth-like relies on “Stacks” or “Last-in-first-out” (LIFO) are processed left to right. This has two features: push and pop.
  • Stack Based in also Turing Incomplete, which means that the operations do not have loops. That means that the program stops repeating or running, avoiding bugs and malicious codes.
  • Reverse Polish Notation: RPN is a method of placing the operation function at the end of a sentence. It is also called “postfix notation”.

Forth-like programming language

Forth-like Is a programming language that has the ability to pile or compile commands for later execution. This language is applied to bitcoin script because it is very malleable, but it is also very straightforward.

Users define and run subroutines call words. Words are any and all syntactic elements, including variables and basic operators; so “+” is not simply an addition symbol but is considered a word.

Linear Data Structures and “push” and “pop” function

As I mentioned, push/pop relies on a linear structure. This is simply a sequential collection of instructions or commands. The push/pop function occurs only at one end
of the sequence (which is the top of the stack in this case). This is a single, linearly linked list of commands, with a pointer to the top of the element.

Alright, so Alice wants to send Bob her Bitcoin transaction, so she will use her previous UTXOs as the input for her new transaction with Bob.

Before Bob can receive and spend his transactions from Alice he must unlock each transaction with his scriptkey, which is the unlocking script. Thus when Bob wants to
spend the transactions he once received from Alice, he will create an input with his UTXOs.

A basic script looks something like this:

Ex. <sig><Pubk> + DUP HASH160 <Pubkhash> EQUALVERIFYCHECKSIG

Script Explanation:

scriptsig (unlocking script) + scriptpubkey (locking script)

Validation Process

<signature><Publickey> OP_DUP OP_HASH160

<Publickeyhash> OP_EQUAL OP_CHECKSIG

The order of operation executions is from left to right. Operators are removed from the script and added to the stack using the “Last In First Out” method.

In the above example the operations are executed in the following way:

  • First, <signature> is moved into the stack.
  • Then <Publickey> is moved into the stack.
  • OP_DUP: which duplicates the top item on the stack, which is the <Publickey>.
  • HASH160: this function hashes the top item, which is the public key. So the public key is sent as a hash.
  • OP_EQUAL: this operation checks whether the two values of the hashed public key are the same.
  • OP_CHECKSIG: verifies if the signature is true.

Push:

Push this is the process of adding an element to the collection or pile of commands in a linear format. After a command is “pushed” from the stack, it is later “popped” back on.

Pop:

Pop removes the most recent element added to the stack. The most current element will then be the one on top of the “pile”. The item is popped in sequential order and
therefore indicates the necessary order of operation execution.

It is a simple process of dealing with the top-most operation in sequence. Push/Pop is just like taking one item from the top, like taking the top plate from a pile of plates. Just like taking a dish off the top of a pile of dishes, the last opcode added (the one on top) is the first one that is removed; hence “last-in-first-out”.

Opcodes

Opcodes are operation codes, script words, or commands/functions. It is by way of this semantic true or false programming language that messages are written, and
transactions are sent and received successfully. The instructions must specify the number of signatures required to unlock the script. They also indicate the amount of
coin that is sent, along with the address of the recipient.

The following is a list of opcodes essential, though not completely conclusive to Bitcoin
script.

“Stack-based Script” operation codes: opcodes

Opcodes:

Operation codes are used to remove items, perform calculations, and then the result is added back onto the stack.

Ex. 2 3 OP_ADD 6 OP_EQUAL

OP_ADD: this operation removes (‘pops”) 2 items from the stack, add the items together and the returns (“pushes”) the result back onto the stack.

OP_EQUAL: this operation removes (pops) two items from the stack to compare and check the values to see if they are equal.

If the values are equal, then the result is TRUE and the items can be returned back to the stack.

“scriptPubKey and scriptSig”

scriptPubKey: this is a locking script, and becomes part of the output of a new Bitcoin transaction.

scriptSig: this is the unlocking script that is necessary to satisfy the conditions placed on the new output by the scriptPubKey.

Ex. <sig><Pubk> [+] DUP HASH160 <PubKHash> EQUAL VERIFY CHECKSIG

Scriptsig: <sig><Pubk>

A digital signature is created by the owner of a public key. This ensures that the funds promised are available to use. Both the digital signature and public key must be
satisfied in order to unlock the script.

Scriptpubkey: <PubKHash>

The locking script contains a public key hash, which is also the “Bitcoin Address.”

DUP opcode: this duplicates the topmost item on the stack and pushes the result back into the Stack.

HASH160 opcode: Hashes the topmost item in the stack.

Ex. A = RIPEMD160 (SHA-256(X))

EQUALVERIFY: This operation decides if the script is TRUE or FALSE. This compares <Pubkhash> to the value from the locking script with the <Pubkhash> value that was calculated from the <Pubk>.

The results of the opcodes are pushed back into the stack. If the script is TRUE then the program continues. If the equation is FALSE then the program stops.

The following charts are a depiction of the sequence of opcodes with their outcomes.

In all OP_ is the prefix for every Bitcoin opcode.

Multisignature Transactions

Conditions: In multi-sig transactions, all people must verify the transaction for the outputs to be unlocked.

Application: These can be useful anytime more than one person’s approval is needed or desired.

M-of-N Scheme: Any combination of the three valid signatures will unlock the script.

M: Is the least number of required signatures.

Script Format: M <Public Key 1> <Public Key 2> ... <Public Key N> N CHECKMULTISIG

Example: 2 of 3 MultiSig: Two of three of the valid signatures are needed.

Script Example: 0 <Signature Bob> <Signature Charlie> 2 <Public Key Alice> <Public Key Bob> <Public Key Charlie> 3 CHECKMULTISIG

“0”: Zero: is used instead of “1” to avoid any errors or bugs. Without the “0” then CHECKSIG will pop out all of the opcodes -instead of just one at a time.

CHECKMULTISIG: This opcode pops (removes) all elements in the stack: M+N+2

The script format of a multisig output looks like this:

M <Public Key 1> <Public Key 2> ... <Public Key N> N CHECKMULTISIG

This transaction is also called a 2-of-3 multisig.

2 <Public Key A> <Public Key B> <Public Key C> 3 CHECKMULTISIG

2 out of the 3 people involved must present their signatures in 1 of 3 ways:

Stacked, the sequence looks like this, operating bottom-up.

3
<Public Key C>
<Public Key B>
<Public Key A>
2
<Signature C>
<Signature B>
0

Pay-to-Script-Hash or P2SH

P2SH is the most common script used presently because it is more compact than the earlier version. Here is a comparison.

No P2SH

Locking Script: 2 <Public Key 1> <Public Key 2> <Public Key 3> <Public Key 4> <Public Key 5> 5 CHECKMULTISIG

Unlocking Script: <Sig 1> <Sig 2>

After P2SH

Redeem Script: 2 <Public Key 1> <Public Key 2> <Public Key 3> <Public Key 4> <Public Key 5> 5 CHECKMULTISIG

Locking Script: HASH160 <Hash of Redeem Script> EQUAL\

Unlocking Script: <Sig 1> <Sig 2> <Redeem Script>

NOTE: The responsibility for supplying the conditions to redeem a transaction transfers from the sender to the recipient who presents the redeeming script

Script outcome: Hash function: SHA 256 and then RIPEMD160

Result: 15 bits (compared to the unhased which is over 3000 alphanumeric characters)

Unlocking Script: <Sig 1> <Sig 2> <2 Public Key 1 Public Key 2 Public Key 3 Public Key 4 Public Key 5 5 MULTISIG>

Combine Bitcoin Scripts: 2 Steps

1: The redeemer script is matched against the hash to see if it matches.

<2 Public Key 1 Public Key 2 Public Key 3 Public Key 4 Public Key 5 5 MULTISIG> HASH160 <HASH OF REDEEM SCRIPT> EQUAL.

If TRUE then Step 2: If true then the traditional multisig unlock functions automatically

<Sig 1> <Sig 2> 2 Public Key 1 Public Key 2 Public Key 3 Public Key 4 Public Key 5 5 CHECKMULTISIG

P2SH Address: 3KP3okFKoGs53JqgyGB27pqaum8tCz2BvW

Flow Control

One of the most interesting aspects of programming is Flow Control. This means that certain conditions are used to detect which commands get executed and when.

The following chart depicts the process of bitcoin script with condition opcodes. As an aside, this is an atypical format to use.

NOTE: Flow control can also work using the VERIFY statement.

This opcode is popped on to the stack CONDITION IF Opcode pops out of the Condition and checks if it is TRUE or not

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

STATEMENT A ENDIF If the IF opcode returns FALSE then the ELSE block gets executed and STATEMENT B is pushed onto the stack.

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

END IF

Multisig transactions can be written to work as Flow Control script. In the instance of a 1-of-2 Multisig only of the two signatures are necessary to verify the transaction.

Locking and Unlocking Script

When Bob wants to spend his new Bitcoin, he must first unlock the script. Alice would have locked the script when she sent her transaction to Bob’s address.

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.

Locking Bitcoin Script or 1-of-2 Multisig

IF <Alice’s Public Key> CHECKSIG ELSE <Bob’s Public Key> CHECKSIG ENDIF <Alice’s Signature> 1 Bob’s unlocking script is <Bob’s Signature> 0 FALSE “0”

Locktime

Basically, a timelock is a primitive smart contract that uses time restrictions on Bitcoin spending. But locktime gets ignored if the sequence numbers for every input are ffffffff. However, Locktime is a way to time-delay a transaction. This was originally designed as a way to perform insecure high-frequency trades. If the locktime is greater than or equal to 500,000,000, it’s a Unix timestamp. If it’s less than 500,000,000, it’s a block number. This way, transactions can be signed but unspendable until a certain point in Unix time or block height is reached.

The central problem with a locktime is that the recipient of the transaction has no certainty that the transaction will be good when the locktime comes. This is similar to a
post dated paper cheque -it might bounce if it is not cashed on time. With a locktime, the sender can spend the inputs prior to the locktime transaction getting into the
blockchain, thus invalidating the transaction at locktime.

Below is a chart of the three timelocks used in Bitcoin:

CHECKLOCKTI MEVERIFY or CLTV: 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.

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

CVS: 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.

Transaction Locktime (nLocktime): “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.

Overview and Conclusion

By now you should understand many of the basic and fundamental concepts that enable the successful operation of Bitcoin Script.

Before you go though, let’s review some of what we have learned about the Bitcoin Script.

Bitcoin Script is the programming language that makes the digital transactions of the currency possible and traceable. The language the script uses operates in a linear
process; operations running from left to right.

The programming language that Bitcoin relies on is: forth-like, stack-based, with reverse polish notation.

Bitcoin Script is designed to function in a linear sequence; one operation functioning after the other. This is a crucial function so that operations occur precisely in their
desired order. This also means that they can be easily added to, and new instructions are not capable of affecting the earlier operations of the script. In order to maintain a kind of simplicity the design that makes the script more secure than other programs, it has certain limitations. Among these “limitations” is that the language is Turing
Incomplete, which means that the program cannot operate on loops.

Each Bitcoin transaction relies on specific inputs and outputs. The input description of input v. output is not mutually exclusive. Bitcoin is a series of digital transactions.
Therefore, it is only the transactions themselves that are traded, there are no physical coins or currency. But like a physical coin, the serial number remains the same as it
moves from one owner to the next, and a dollar remains a single dollar, even when it is part of a larger balance.

The input then is the first stage of any transaction which includes the necessary details with the amount of the transaction, the fees, the address of the sender and receiver, as well as both participants’ public and private keys.

The output is also the UTXO, unspent transactions, that the new owner of the Bitcoin will use for his input when he goes to spend/send his newly acquired Bitcoin.

Transactions in process are locked and must be unlocked with the correct signature from its intended new owner. The data necessary to unlock the script is the ScriptSig, which is a crucial aspect of the encryption processes of any Bitcoin transaction.

Both public and private keys are hidden behind the double hash SHA-256. This maintains privacy but also allows for radical transparency. The public key is hashed first
with SHA-256. Then, that resulting hash is hashed with RIPEMD-160. The final outcome is a 160-bit alphanumeric hash.

Remember, public keys are shared, private keys are not shared. It is the task of the Bitcoin miners to solve the cryptographic puzzle in order to confirm and verify that the
private and public keys of all transactions match. UTXOs are thus locked by the ScriptPubKey until the correct scriptSig unlocks the encryption of the cryptographic
hash.

The final 4th section of this article uses several basic examples of Bitcoin opcodes and scripts. These demonstrate that the script relies on the combination and correct
ordering of operations for the program to execute itself correctly. T,he transaction is only confirmed and released to the new address once the script is approved and the
signatures are verified. As also discussed, a transaction can require more than one signature, or a multsig, which simply means that more than one private key is necessary to unlock the script.

Ultimately, the script dictates the order of operations, while the miners compete to approve the transactions and for the potential remunerations of fees and the creation
of new Bitcoin. Miners approve that the balance being sent is available, that it is going to the correct address with the corresponding private key, and that the transaction does not get double spent.

When the transaction is approved it is added as a new block to the immutable Bitcoin blockchain. Within that new block is the history of its transactions.

So that’s all for now! I hope that you feel more comfortable with the central concepts of Bitcoin Script.

Easy as 1-2-3.

But really it’s more like: OP_0, OP_1, OP_2