Glossary

Opcode

An opcode is a single instruction in Bitcoin Script that defines what operation a node performs when validating a transaction.

Key Takeaways

  • An opcode is a single-byte instruction in Bitcoin Script that tells a node what operation to perform when validating a transaction: push data, check a signature, hash a value, or enforce a timelock.
  • Bitcoin has roughly 100 active opcodes spanning constants, flow control, stack manipulation, arithmetic, cryptographic hashing, signature verification, and timelocks. Around 15 opcodes were disabled by Satoshi in 2010 to prevent denial-of-service attacks.
  • The 2021 Taproot upgrade introduced Tapscript, which replaced OP_CHECKMULTISIG with the batch-verifiable OP_CHECKSIGADD and added OP_SUCCESS opcodes as a clean upgrade path for future soft forks.

What Is an Opcode?

An opcode (short for "operation code") is a single instruction in Bitcoin's scripting language, Bitcoin Script. Each opcode is encoded as one byte (values 0x00 through 0xff), giving a theoretical maximum of 256 possible instructions. When a node validates a transaction, it reads the script byte by byte and executes the corresponding operation for each opcode it encounters.

Bitcoin Script is a stack-based language inspired by Forth. It is intentionally not Turing-complete: there are no loops, no recursion, and scripts must terminate within strict resource limits. This design keeps transaction validation deterministic and fast, preventing any single transaction from consuming unbounded computation. Opcodes are the building blocks that make this controlled programmability possible.

Every Bitcoin transaction contains scripts that define the conditions under which funds can be spent. The locking script (scriptPubKey) on an output specifies what must be proven, and the unlocking script (scriptSig or witness) on a spending input provides that proof. Both scripts are composed of opcodes and data pushes, evaluated together by every validating node on the network.

How Opcodes Work

Bitcoin Script uses a stack-based execution model. The interpreter processes a script from left to right, maintaining a main stack and an alt stack. Data-push opcodes place items onto the stack. Operational opcodes pop their operands from the stack, perform a computation, and push results back. A script succeeds if execution completes without error and the top stack element is truthy (non-zero).

Consider the standard Pay-to-Public-Key-Hash (P2PKH) script, which locks funds to a specific public key hash:

OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG

Here is what happens step by step when a node evaluates this script:

  1. The unlocking script pushes the signature and public key onto the stack
  2. OP_DUP (0x76) duplicates the public key on top of the stack
  3. OP_HASH160 (0xa9) pops the duplicated key, hashes it with SHA-256 then RIPEMD-160, and pushes the result
  4. The 20-byte pubkey hash from the locking script is pushed onto the stack
  5. OP_EQUALVERIFY (0x88) checks that both hashes match, failing the script if they differ
  6. OP_CHECKSIG (0xac) verifies the signature against the public key, pushing true if valid

Script Resource Limits

To prevent abuse, Bitcoin enforces strict limits on script execution in legacy and SegWit v0 scripts:

  • Maximum script size: 10,000 bytes
  • Maximum non-push opcodes per script: 201
  • Maximum stack element size: 520 bytes
  • Maximum combined stack and alt-stack items: 1,000

Tapscript (BIP-342) relaxed some of these limits: it removed the 10,000-byte script size cap and the 201 opcode-per-script limit, relying instead on block weight and a per-input signature budget to constrain resources.

Opcode Categories

Constants and Data Pushing

These opcodes push data onto the stack. OP_0 (0x00) pushes an empty byte array (representing false or zero). OP_1 through OP_16 (0x51 through 0x60) push their respective numbers. OP_1NEGATE (0x4f) pushes -1. Opcodes 0x01 through 0x4e push the next N bytes of script data onto the stack. Data-push opcodes do not count toward the 201 non-push opcode limit.

Flow Control

OP_IF (0x63) and OP_NOTIF (0x64) create conditional branches. OP_ELSE (0x67) and OP_ENDIF (0x68) delimit the branches. OP_RETURN (0x6a) marks a transaction output as provably unspendable and is commonly used to embed small amounts of arbitrary data on-chain. OP_VERIFY (0x69) pops the top stack element and fails the script if it is false.

Stack Operations

Stack opcodes rearrange elements without performing computation. OP_DUP (0x76) duplicates the top item. OP_DROP (0x75) removes it. OP_SWAP (0x7c) swaps the top two items. OP_OVER (0x78) copies the second item to the top. OP_ROT (0x7b) rotates the top three items. OP_PICK (0x79) copies the nth item, and OP_ROLL (0x7a) moves the nth item to the top.

Arithmetic

Arithmetic opcodes operate on numeric stack elements. OP_ADD (0x93) and OP_SUB (0x94) perform addition and subtraction. OP_NUMEQUAL (0x9c) checks if two numbers are equal. OP_LESSTHAN (0x9f) and OP_GREATERTHAN (0xa0) perform comparisons. OP_MIN (0xa3) and OP_MAX (0xa4) return the smaller or larger of two values. Bitcoin Script arithmetic is limited to 4-byte signed integers (roughly -2.1 billion to 2.1 billion).

Cryptographic Operations

These are the most computationally significant opcodes. Hashing opcodes include OP_SHA256 (0xa8), OP_HASH160 (0xa9, which performs SHA-256 followed by RIPEMD-160), and OP_HASH256 (0xaa, double SHA-256). Signature verification opcodes include OP_CHECKSIG (0xac) for single-key checks and OP_CHECKSIGADD (0xba) for batch-verifiable multisig in Tapscript.

Timelock Operations

OP_CHECKLOCKTIMEVERIFY (0xb1, added in BIP-65) ensures a transaction cannot be mined before a specific block height or Unix timestamp. OP_CHECKSEQUENCEVERIFY (0xb2, added in BIP-112) enforces a relative timelock: a minimum number of blocks or seconds must pass after the output being spent was confirmed. Together these opcodes enable time-locked contracts, HTLCs, and payment channels.

Disabled Opcodes

In 2010, Satoshi Nakamoto disabled approximately 15 opcodes in a single commit (CVE-2010-5137) after discovering that several of them could be exploited for denial-of-service attacks. Any transaction containing a disabled opcode fails validation immediately.

The disabled opcodes fall into three groups. String and splice opcodes (OP_CAT, OP_SUBSTR, OP_LEFT, OP_RIGHT) were vulnerable to exponential memory consumption: a script could push one byte, then repeatedly duplicate and concatenate it, doubling the element size with each iteration until it exceeded available memory. Bitwise logic opcodes (OP_INVERT, OP_AND, OP_OR, OP_XOR) were disabled as a precaution. Arithmetic opcodes (OP_MUL, OP_DIV, OP_MOD, OP_LSHIFT, OP_RSHIFT, OP_2MUL, OP_2DIV) carried risks of integer overflow and division-by-zero errors.

The removal of these opcodes significantly reduced Bitcoin Script's expressiveness. It eliminated the ability to perform string manipulation, bitwise logic, and general-purpose arithmetic within scripts. This tradeoff prioritized security and simplicity over programmability: a deliberate choice that continues to shape debates about Bitcoin's scripting capabilities today.

The OP_CAT Debate

OP_CAT has become the most discussed disabled opcode. BIP-347 proposes re-enabling it within Tapscript by redefining the OP_SUCCESS126 opcode. The new version would impose a 520-byte maximum on the concatenated result, preventing the original memory explosion vulnerability. Proponents argue that OP_CAT would unlock covenants, transaction introspection, and more complex smart contracts on Bitcoin. As of mid-2026, BIP-347's specification is complete, but no activation parameters have been defined and no soft fork deployment is scheduled. For more on this topic, see the OP_CAT covenant debate deep dive.

Tapscript: Opcode Evolution

The Taproot soft fork (activated November 2021) introduced Tapscript (BIP-342), which made several important changes to how opcodes work within script-path spends of P2TR outputs.

OP_CHECKSIGADD Replaces OP_CHECKMULTISIG

OP_CHECKMULTISIG used a trial-and-skip approach that made it impossible to know which public key verified which signature. This is fundamentally incompatible with Schnorr batch verification, which requires explicit (key, message, signature) tuples.

OP_CHECKSIGADD (0xba) replaces this pattern. It pops a public key, a counter, and a signature from the stack. If the signature is valid, it pushes counter + 1. If the signature is empty, it pushes the counter unchanged. A k-of-n multisig is constructed by chaining OP_CHECKSIGADD calls and comparing the final counter to the threshold:

<sig_n> ... <sig_1>
<key_1> OP_CHECKSIG
<key_2> OP_CHECKSIGADD
<key_3> OP_CHECKSIGADD
...
<key_n> OP_CHECKSIGADD
<k> OP_NUMEQUAL

OP_SUCCESS: A Clean Upgrade Path

Tapscript designates many previously undefined or disabled opcodes as OP_SUCCESSx. These opcodes cause the entire script to succeed unconditionally the moment they are encountered during decoding (before execution even begins). This may sound dangerous, but it is a deliberate upgrade mechanism.

In legacy Script, new features were added by redefining OP_NOP opcodes (for example, OP_NOP2 became OP_CHECKLOCKTIMEVERIFY). OP_NOP redefinitions cannot modify the stack: they can only add a validation condition that causes failure. OP_SUCCESS solves this constraint. A future soft fork can redefine any OP_SUCCESSx opcode to push values, pop values, or enforce arbitrary validation. Making a previously-always-succeeding opcode sometimes fail is a valid soft fork because it only tightens rules.

Per-Input Sigops Budget

Legacy scripts enforce a block-wide sigops limit of 80,000 (weighted) to prevent denial-of-service attacks via computationally expensive signature verification. Tapscript replaces this with a per-input budget calculated as 50 plus the total witness size in bytes. Each signature check costs 50 from the budget. This unifies the weight and sigops constraints into a single metric, simplifying block construction for miners.

Why Opcodes Matter

Opcodes define the boundary of what Bitcoin can do programmatically. Every spending condition, from a simple single-signature wallet to a complex HTLC powering the Lightning Network, is ultimately expressed as a sequence of opcodes. The set of available opcodes determines what types of contracts are possible on Bitcoin.

For layer-2 protocols and off-chain systems, opcodes are especially important. Timelocks (OP_CHECKLOCKTIMEVERIFY, OP_CHECKSEQUENCEVERIFY) enable payment channels and atomic swaps. Signature-checking opcodes secure multisig custody arrangements. Proposals like OP_CHECKTEMPLATEVERIFY (BIP-119) and OP_CAT (BIP-347) aim to expand what is possible by introducing new opcodes through soft forks. For a comprehensive look at how these primitives compose into higher-level functionality, see the Bitcoin Script programmability research article.

Risks and Considerations

Security Surface

Every opcode is a potential attack surface. Bugs in opcode implementations can lead to consensus failures, network splits, or theft of funds. The 2010 disabling of 15 opcodes demonstrates how broad the attack surface can be: vulnerabilities in arithmetic overflow, memory allocation, and string manipulation all emerged from opcodes that seemed safe at first glance.

Ossification vs. Innovation

Adding new opcodes requires a soft fork, which demands broad community consensus. Some participants favor ossification: keeping the opcode set frozen to minimize risk. Others argue that new opcodes are necessary for Bitcoin to support more expressive contracts and compete with alternative platforms. This tension is at the heart of current debates around OP_CAT, OP_CTV, and other proposals.

Script Complexity

More complex opcode sequences increase the risk of subtle bugs in spending conditions. Unlike general-purpose programming languages, Bitcoin Script has no debugger, no test framework, and errors can result in permanently locked or stolen funds. Tools like Miniscript help by providing a structured way to compose opcodes into safe, analyzable spending policies, but developers working directly with raw opcodes must exercise extreme caution.

This glossary entry is for informational purposes only and does not constitute financial or investment advice. Always do your own research before using any protocol or technology.