Script

Locking mechanism for outputs

A diagram showing the basics of the Script language in Bitcoin.

Script is a mini programming language used as a locking mechanism for outputs in bitcoin transactions.

If a full script (unlocking + locking) is valid, the output is "unlocked" and can be spent.

Script Language

What is Script?

Script is a very basic programming language. It consists of two things:

  1. Data – Such as public keys and signatures.
  2. OP_CODES – Simple functions that operate on the data.

Here's a simple diagram of a typical P2PKH script used in Bitcoin:

A diagram showing an example Script in Bitcoin (P2PKH).

For simplicity the diagrams on this page are not showing any OP_PUSHBYTES_XX opcodes, but these are required when pushing data on to the stack. I've also removed the OP_ prefixes from the opcodes.

Here's a list of all the possible Opcodes you can use in bitcoin scripts.

tool-661eba365d079
Tool Icon

Script

Decode and encode a script.

0 bytes
0 characters
0 secs

Execution

How is Script executed?

A complete script is run from left-to-right. As it runs, it makes use of a data structure called a stack.

Data gets pushed on to the stack.

Animation showing data being pushed on to the stack.

Opcodes can then pop elements off the stack, do something with them, then optionally push new elements back on to the stack.

Animation showing an OP_CODE performing an operation on some data on the stack. The OP_DUP opcode for example duplicates the top element on the stack.

Validity

Here's an example of the full execution of a valid P2PKH script:

Animation showing a full P2PKH Script successfully validating because a single OP_1 is left on the stack after the script has finished executing.

A complete script is determined to be valid or invalid after it has finished executing.

A script is valid if the only element left on the stack is a OP_1 or greater.

A script is invalid if:

  1. The final stack is empty
  2. The only element left on the stack is OP_0
  3. There is more than one element left on the stack at the end of execution.
  4. The script exits prematurely (e.g. OP_RETURN).

Location

Where is Script used in Bitcoin?

A locking script (ScriptPubKey) is placed on every output you create in a transaction:

A diagram showing the location of a locking script (ScriptPubKey) on a transaction output.

An unlocking script (ScriptSig or Witness) must be provided for every input you want to spend in a transaction:

A diagram showing the location of an unlocking script (ScripSig) on a transaction input.

Every node will then combine and run these two scripts for each input in every transaction they receive to make sure they validate. If the unlocking scripts on inputs do not successfully unlock the locking scripts on the outputs being spent, then the transaction is considered invalid and will not be relayed or mined in to a block.

Usage

Why do we use Script in Bitcoin?

Why do we use a mini programming language for locking up bitcoins? Why not just use a simple public key and signature comparison and do away with all of these opcodes and stacks?

Well, because by using Script you can create different types of locks by using different combinations of OP_CODES.

For example, here are some cool locking scripts you can create:

1. Math Puzzle

To spend this output, you need to provide two numbers that add up to 8.

A diagram showing a mathematical puzzle being used as a locking script.

This may not be the most secure locking script in the world, as anyone can figure it out and unlock it.

2. Hash Puzzle

Here you just need something that hashes to the same result as what's inside the locking script.

A diagram showing a hash puzzle being used as a locking script.

3. Hash Collision Puzzle

This is a cool one. You can unlock it by providing two different strings of data that produce the same hash result.

In other words, it acts as an incentive to find a "hash collision".

A diagram showing a hash collision puzzle being used as a locking script.

This particular locking script can be found on this output. However, the script has been wrapped in a P2SH locking script, so you can't actually see the original locking script (until someone unlocks them).

All of the above locking scripts are non-standard. Whilst these scripts are valid (and can be mined on to the blockchain), typical Bitcoin Core nodes will not relay them from their memory pools, which makes it difficult for them to get mined in the first place.

Standard Scripts

What are the most common Script patterns in Bitcoin?

Despite being able to create a variety of different locking scripts with various combinations of OPCODES, most nodes will only relay a handful of "standard scripts":

Legacy

A diagram showing a complete list of the legacy standard scripts used in bitcoin.

These were the standard scripts available in bitcoin between 2009 and 2016 (before the Segwit upgrade).

They are unlocked via the ScriptSig field.

Although these are not used as much today (in favour of the newer Segwit scripts below), they're still perfectly valid and you can use them for locking up your coins if you want to.

Segwit

A diagram showing a complete list of the segwit standard scripts used in bitcoin.

These standard scripts were introduced after the Segwit upgrade in 2016 (and then also the Taproot upgrade in 2021). They were basically introduced to replace the legacy P2PKH and P2SH locking scripts above.

They are unlocked via the Witness field.

These locking scripts do not actually use the fully-fledged Script language.

Instead, each locking script has its own specific pattern, and they are executed in a set way internally when being unlocked. So they have actually done away with the Script language to a degree (except for when you wrap a fully-fledged script inside a P2WSH).

So when I said "why not just use a simple public key and signature comparison and do away with all of these opcodes and stacks?", well, that's what these scripts have done.

Why don't nodes relay non-standard scripts?

I know, it's a shame.

However, not every combination of OP_CODE has been tested. So if nodes relayed every non-standard script they received, it would introduce the risk of an attack from someone spamming the network with scripts that take a long time to verify. This could "clog up" nodes and bring the network to a halt.

On the other hand, the standard scripts have been thoroughly tested and can be validated quickly. So the whole non-relaying of non-standard transactions is just a safety measure.

Non-standard scripts are valid, they are just not relayed. Even though a non-standard transaction does not get relayed between memory pools, it can still be mined in to a block. So if you want a transaction with a non-standard script to be added to the blockchain, you either need to send it directly to a miner who will mine it for you, or mine it on to the blockchain yourself.

Limits

What is the maximum size of a script?

Scripts in bitcoin have certain limits on their size. There are two types of limits:

  1. Validity Limits. Any transaction that contains a script that exceeds these limits will be considered invalid. This means it will be rejected by nodes and cannot be mined in to the blockchain.
  2. Standardness Limits. A transaction can break these limits and still be mined in to the blockchain, but nodes will consider them non-standard and will refuse to relay them between memory pools.

1. Validity Limits

A diagram showing the limits for a valid script.

These limits can be found in script.h.

These limits only apply during script execution. So you could place a ScriptPubKey on an output that exceeds these limits and it would get mined. But when you come to try and spend it as an input (i.e. when the script is being executed), the spending transaction will be considered invalid. In other words, the output would be unspendable.

2. Standardness Limits

A diagram showing the limits for a standard script.

So whilst it's valid for a transaction to exceed these limits, it's going to be difficult to get it mined in to the blockchain unless you can mine it yourself or get a miner to add it to the blockchain for you.

These limits can be found in policy.h.

Summary

Script is just a mini programming language used in Bitcoin to provide the locking mechanism for outputs.

When a node receives the spending transaction, it will combine both of these scripts together and run them. If a OP_1 (and nothing else) is left on the top of the stack after the script has finished executing, then the script is valid and the output can be spent.

The newer segwit locking scripts have moved away from using traditional Script slightly, but the Script language is still used for legacy locking scripts, and can also continue to be used within the newer P2WSH locking script.

The script is actually a predicate. It's just an equation that evaluates to true or false. Predicate is a long and unfamiliar word so I called it script.
Satoshi Nakamoto, bitcointalk.org

Resources