For the complete documentation index, see llms.txt. This page is also available as Markdown.

Script

Understanding basics of Script and stack based compilation

Script is the stack-based language used in transaction outputs and inputs. An output's locking script (scriptPubKey) sets the condition for spending it; a spending input's unlocking script (scriptSig) supplies the data that satisfies that condition. To validate an input, the node evaluates the unlocking script followed by the locking script against a shared stack; the input is valid if evaluation succeeds with a true value on top of the stack. Because the outcome is a single true/false result, a script is a predicate. There are no loops or jumps.

This page specifies the execution model, the number encoding, the consensus limits by era, and the formal grammar. The individual opcodes are on the Opcodes page.

In the late 60's Charles 'Chuck' Moore developed FORTH as a fully interactive stack based programming environment that ran on a microcontroller and provided the user with a simple, command line entry based means to enter commands and build FORTH words (operations) and programs (functions).

FORTH is different to many programming languages in that it runs 'live' while the programmer is working on their software, allowing new 'words' to be defined, tested, redefined and debugged without having to recompile or restart the system.

Bitcoin Script is heavily inspired from FORTH in its makeup. It adds some grammar changes and removes capabilities such as jump instructions and loops and is different in that way from FORTH

Execution model and consensus rules

This section specifies how the Script engine evaluates a script and the consensus limits that govern that evaluation. The per-opcode behaviour is on the Opcodes page; this page covers the language, the number model, the limits by era, and the grammar.

Ground truth. The execution model derives from EvalScript/VerifyScript in src/script/interpreter.cpp, the number model from src/script/script_num.h/.cpp, and the limits from src/consensus/consensus.h. The formal grammar and the Genesis/Chronicle rule changes are sourced from the consensus specs. Code citations are pinned to release v1.2.2 (commit 879fc8b).

Evaluation

To validate a transaction input, the node evaluates its unlocking script (scriptSig, from the spending input) followed by the locking script (scriptPubKey, from the output being spent):

  1. The unlocking script is evaluated first. The resulting main stack is carried forward; the alt-stack and conditional state are reset before the locking script runs.

  2. The locking script is then evaluated against that main stack.

  3. Opcodes are processed left to right. Data pushes place one element on the stack; operations pop their inputs and push their results (Opcodes).

  4. There is a single main stack shared across the two scripts plus a separate alt-stack (OP_TOALTSTACK/OP_FROMALTSTACK). There are no loops or jumps.

  5. The script succeeds if, at the end, the stack is non-empty and the top element is true (see the truth-value definition on the Opcodes page). Any error (bad opcode, failed OP_VERIFY, exceeded limit, …) makes the input — and therefore the transaction — invalid.

The clean-stack rule additionally requires that exactly one element remain after evaluation. It is enforced pre-Genesis and by policy after, and (from Chronicle) can be opted out of for transaction version > 1 (see Malleability opt-outs).

Number encoding

Numeric values (CScriptNum) are encoded as follows (script_num.h, int_serialization.h):

  • Little-endian, least-significant byte first.

  • Sign-magnitude: the sign is the most-significant bit (0x80) of the last byte. If the magnitude's top byte would already have that bit set, an extra byte (0x00 for positive, 0x80 for negative) is appended to hold the sign.

  • Zero is the empty byte array. Negative zero (0x80) is not a distinct value and is not minimally encoded.

  • Minimal encoding: an encoding must not carry a redundant most-significant byte — (last_byte & 0x7f) == 0 is non-minimal unless dropping it would push the sign bit into the next byte (e.g. +255 is 0xff 0x00, which is minimal). This is enforced when the minimal-data flag is active.

  • Range/overflow: a number longer than the era's maximum serialized length is rejected. When a number is read as a machine integer, getint/getint64 saturate to the int32/int64 bounds rather than wrapping.

Pre-Genesis the backing type is a 64-bit integer capped at 4 bytes; from Genesis the engine uses an arbitrary-precision (big-integer) backing bounded only by the maximum-script-number-length limit.

Limits by era

All values from src/consensus/consensus.h:

Limit
Pre-Genesis
Genesis
Chronicle

Max operations per script

500 (was 201 before Nov 2018)

unlimited (UINT32_MAX)

—

Max script size

10,000 bytes

unlimited (UINT32_MAX, P2P-bounded)

—

Max script number length

4 bytes

750,000 bytes

32 MB (32 × ONE_MEGABYTE)

Max script element size

520 bytes

removed (see stack-memory rule)

—

Max stack elements

1,000

removed (see stack-memory rule)

—

Max public keys per multisig

20

UINT32_MAX (2³²−1)

—

Stack memory usage

n/a

Σ(32 + element_size) over stack + alt-stack, configurable

—

A dash means the value is unchanged from the previous era. From Genesis, the per-element and per-count stack limits are replaced by a single stack memory usage consensus rule: the sum over every element on the main and alt stacks of 32 + (element size in bytes) must not exceed the configured limit. That limit is a consensus value miners coordinate on; the specific number is operator policy.

Formal grammar (Genesis)

From Genesis, a script must be grammatically valid — it is parsed against a formal grammar, and a script that does not conform is invalid. The grammar's structural core is (full production list in the Genesis specification):

Two consequences are worth calling out:

  • PUSHDATA-only unlocking scripts: from Genesis, <unlocking-script> may contain only constants — i.e. an unlocking script may contain only data pushes, no functional opcodes. (This is partially reversed at Chronicle for transaction version > 1 — see below.)

  • OP_RETURN and trailing data: a locking script may end with OP_RETURN followed by arbitrary non-script data, which is not parsed as script.

Chronicle malleability opt-outs

At Chronicle, transactions signed with a version field greater than 1 may opt out of a set of malleability-prevention restrictions during script evaluation (transactions with version 1 keep them). Each restriction below links to where it is defined in these docs:

  • the minimal-encoding requirement — numbers and data pushes must use their shortest form (see Number encoding and the minimal-push rule);

  • LOW_S — a signature's S value must be in the lower half of the curve order, giving a canonical signature (part of the signature-encoding checks applied by OP_CHECKSIG; see also Sighash);

  • NULLFAIL / NULLDUMMY — a failed signature check must leave an empty signature, and the extra OP_CHECKMULTISIG dummy item must be empty (see OP_CHECKSIG/OP_CHECKMULTISIG);

  • MINIMALIF — the condition consumed by OP_IF/OP_NOTIF must be exactly OP_0 or OP_1;

  • the clean-stack requirement — exactly one element may remain after evaluation;

  • the data-only-in-unlocking-script requirement (from the Genesis grammar) — functional opcodes are again permitted in unlocking scripts.

When an unlocking script does run functional opcodes, note that after it finishes the main stack is carried into the locking script but the alt-stack and conditional state are cleared, and an OP_RETURN in the unlocking script ends only the unlocking script (not the whole evaluation). The maximum script-number length is also raised from 750,000 bytes to 32 MB at Chronicle.

See the Protocol Upgrade History page for activation heights.

Last updated