Before we begin our descent into an explanation of Bitcoin script, it is helpful to remember that Bitcoin was 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 shared on multiple networks also because of the use of blockchain, every time a coin, or more correctly, a transaction, is made, there is an immutable record of the exchange.
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.
- Transactions Basics
- Programming Language and SHA-256
- Looking at Cryptographic Details of Bitcoin Script
- Operation Codes and Script in Detailed Diagrams
- Article Overview and Conclusion
Each of the five sections can be read as a self-contained discussion of Bitcoin Script, but if you want to know more keep reading the article in full. The fourth 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 are organized from most basic to most complex:
Complete Article Outline
- Transaction Basics
- Programming Language and Script
- The Qualities of Bitcoin Script:
- 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
- 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
- Multisignature Transactions
- Pay-to-Script-Hash or P2SH
- Flow Control
- Locking and Unlocking Script
- Article Overview and Conclusion
After reading this article you should feel much more comfortable with the following aspects of Bitcoin script:
- Programming Language
- SHA-256 and hash functions
- Private Key
- Public Key
- 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. If you wish to learn to code, there is not detailed enough information here. Nevertheless, you should feel pretty comfortable with the fundamentals of Bitcoin Script by the time we are done.
The essence and value of Bitcoin is in the cryptographic transactions that are exchanged as monetary currency. T 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 have been completed, 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
Similar to emails, Bitcoin can be sent and received. 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 is hashed, and that hash then becomes the cryptographic signature that will be 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.
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.
So, if you are still interested in Bitcoin script, and you want to know more about how the script works, then keep reading.
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 these computations are done using computer 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 uses 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, which trades on the ideal that 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, rather a bitcoin is a history of signatures, secured using cryptography. To own bitcoin is to have in your possession a complete history of the transactions. Ownership includes a pair of keys that enables you to keep track of and use your bitcoin; a public key that is shared, and a private key that is not.
The design of Bitcoin script is to provide flexible parameters necessary to perform a transfer. Many operations were disabled by creator Santoshi Nakamoto, including multiplication in order to keep the script simple in programming terms.
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 and is only redeemable by a digital signature with an input that allows the program to be returned successfully; this constitutes a valid transaction and the bitcoin will be moved 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. Bitcoin was designed using 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 limitation 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 so that one direction is executed after the other. This means that 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. By using a script that is Turing Incomplete the system is protected against this kind of vulnerability.
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, and thus it’s easy to create unintended behavior, causing bugs. Bugs in a smart contract make coins vulnerable to unintentional spending.
These bugs were a serious problem in the DAO (Decentralized Autonomous Organization), a Turing-complete smart contract that ended with the Ethereum Classic hard fork.
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:
- A private key
- A public key – derived from the hash of the private key
- 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
A Bitcoin private key is a single unsigned 256-bit integer, that consists of 32 bytes. A private key is secret, as indicated by its name. A private key is known only to its owner. Private keys are a sequence of randomly generated numbers. For Bitcoin transactions, to unlock and spend a transaction, the spender must have the corresponding private key on the blockchain so that she can spend the funds.
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. The older formally used public keys are uncompressed and are 65 bytes called x, with the prefix, “0x04”, followed by two 256-bit integers called x and y (2 * 32 bytes).
To know more about Private Keys check it out here.
A signature is a cryptographically generated alphanumeric sequence that proves that the operation occurred. A signature is generated from a combination of the hash of a transaction to be signed, as well as 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 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 that transfer ownership of a transaction from one wallet (or Bitcoin address) to another. Each digital transactions has requisite inputs in order for the desired output to be 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. Each key is made up of a string of alphanumeric characters. 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 the account balance of an address, as well as the history of all of its transactions. This information is shared publicly so that others can see your transactions as well as 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 and is necessary in order for a script to be valid and for the transactions to be completed to the parameters of the initial message. The private keys are secured by the cryptographic hash function, and the miners must 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 using 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.
- 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.
- Bob’s digital signature and public key are confirmed in sequence before they are verified.
VERIFY is the variable that is written into the unlocking script. VERIFY is a Guard Clause and is also used for Flow Control. VERIFY can be added to the sequence of opcodes. This is an opcode used in the middle of a script in order to ensure that certain parameters are met throughout the sequence and not just 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, the code will halt and stop running.
Say Alice wants to provide conditions under which Bob receives his Bitcoin, like another signature, this 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, but are designed for ownership to be passed from one address to the next.
You might still be wondering: How is a cryptographic signature made? And how do Bitcoin miners approve transactions?
Bitcoin’s script uses public keys and private keys that are cryptographically generated. This means that addresses are created using one-way mathematical functions. One-way mathematical functions make is so that the input is easily computed, but 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.
So, the message starts out something like this:
(NOTE: This is not a real transaction, but a depiction of the internal information of a transaction.)
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: 02473044022056e615f489f80887760517c15e50a5667c0fa4e39b89e52dd222779e3bb 81a0d022029379f49226d407c166eea7cab69a85423d038de88e6997e1bcdd9dfb274e Ab50121029403fb4f07e211c143ae26f9300b1de2ab1e763d28ec305365b3a09a3b678fOutput Scripts
Output Script: 02473044022056e615f489f80887760517c15e50a5667c0fa4e39b89e52dd222779e3bb 81a0d022029379f49226d407c166eea7cab69a85423d038de88e6997e1bcdd9dfb274e 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, while infeasible to reverse.
To read more about hashing on the blog, check it out here: What is Blockchain Hashing
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 digital, cryptographically generated code that is 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.
Elliptical curve cryptography is what is used by bitcoin (and Ethereum, among other cryptocurrencies), for 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.
The following is the basic image a ECDSA on a grid:
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 being 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 has a UTXO worth 10 bitcoins, but only requires 2 bitcoins for their transaction, then the entire 10 bitcoins is sent with two outputs being produced:
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.
Below is a more realistic image of what cryptographic transactions look like.
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. When the computation is solved a new signature is created. 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.
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. The security of the blockchain is maintained by a cryptographic chain of computations and blocks.
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. The transaction approved first will be reflected in the state of the blockchain.
If you want to know more about Consensus Protocol read about it here on the blog.
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.
Here are some images. The first is uncompressed and is 64 bytes, while the second was serialized using DER and is only 32 bytes. The basic difference is obviously the size, and increased ease to manag the data.
Uncompressed Standards for Efficient Cryptography (SEC) format:
The standard for serializing signatures (and lots of other things, for that matter) is called Distinguished Encoding Rules (DER) format. DER format was used by Satoshi to serialize signatures:
The following charts have broken down the main features of the serialization process.
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|
|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 are scripted to require multiple signature. Multisignature means the transaction requires more than one key for authorization. Requiring multiple signatures is generally used to divide responsibility for possession of the 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”.
To read more about Coding here.
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 used for bitcoin script because it is very malleable, but 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
scriptsig (unlocking script) + scriptpubkey (locking script)
<signature><Publickey> OP_DUP OP_HASH160
<Publickeyhash> OP_EQUAL OP_CHECKSIG
Operations are executed in order 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 would be 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 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 removes the most recent element that has been added to the stack. The most current element will then be the one on top of the “pile”. The item is popped in order of sequence and therefore necessary operation execution.
The following is an illustration of the process of push/pop.
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 one added (on top) is the first one to be removed, hence “last-in-first-out”.
Take a look at the below image and you will see a few familiar items like hashes of keys and opcodes running the program.
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 can be sent and received with specific instructions. The instructions need to specify how many signatures are needed to unlock the script. They also indicate the amount that is being sent, and to which address.
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 add the result back to 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
A digital signature is created by the owner of a public key and 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.
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 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 meant to depict the sequence of opcodes and their outcomes.
In all OP_ is the prefix for every Bitcoin opcode.
|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.|
|N||Is the total number of keys.|
|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.
<Public Key C>
<Public Key B>
<Public Key A>
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.
|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>|
|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|
One of the most interesting aspects of programming is Flow Control. By using certain conditions one can 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|
Multisig transactions can be written to work as Flow Control script. In the instance of a 1-of-2 Multisig only of these two signatures is needed 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
|<Alice’s Public Key> CHECKSIG|
|<Bob’s Public Key> CHECKSIG|
|<Alice’s Signature> 1|
|Bob’s unlocking script is||<Bob’s Signature> 0|
Basically, a timelock is a primitive smart contract that uses time restrictions on Bitcoin spending. When locktime is ignored if the sequence numbers for every input are ffffffff. However, Locktime is a way to time-delay a transaction. It was originally designed as a way to do high-frequency trades which were insecure. 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:
|CHECKLOCKTIMEVERIFY 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.|
|CHECKSEQUENCEVERIFY 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, 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 function is crucial so that operations occur in the desired order and can be easily added to, without the capability of affecting the operations of the earlier 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. Because Bitcoin is a series of digital transactions, it is actually the transactions themselves that are traded only there is no physical coin. 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 that are in process are locked and must be unlocked with the correct signature of 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.
In order to maintain privacy within a system of radical transparency both public and private keys are hidden behind the double hash SHA-256. The public key is first hashed with SHA-256, then the resulting hash is hashed with RIPEMD-160, so the final outcome is a 160-bit alphanumeric hash.
While public keys may be shared, private keys are not and 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 cryptographic hash.
As demonstrated in the final 4th section of this article with several basic examples of Bitcoin opcodes and scripts, the script relies on the combination and correct ordering of operations in order for the program to execute itself correctly. If the script is approved and the signatures are verified, then the transaction will be released to the new address. 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.
Once the transaction is approved it becomes a block in the immutable Bitcoin blockchain, and within the 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