TeachMeBitcoin

OP_VER - The Disabled Version Opcode

From TeachMeBitcoin, the free encyclopedia Reading time: 3 min

17. OP_VER — The Disabled Version Opcode

Overview

OP_VER is opcode 0x62 in Bitcoin Script. Despite occupying a byte immediately adjacent to OP_NOP (0x61), OP_VER has a radically different status: it is a disabled opcode that causes any script containing it to be immediately invalid, regardless of whether it appears in an executed or unexecuted code path. Unlike OP_RESERVED, which only fails when executed, OP_VER fails at validation time even in dead branches.

Original Intended Purpose

Based on early Bitcoin codebase history and commentary, OP_VER was intended to push the current protocol version number onto the stack, potentially enabling version-dependent script logic. A script could in theory have branched on the protocol version to behave differently in different protocol eras.

Hypothetical (never worked in practice) intended use:
OP_VER           -- push current protocol version
<expected_ver>   -- push expected version
OP_EQUAL         -- check if they match
OP_IF ... OP_ENDIF

This design would have been deeply problematic: if the protocol version changed, previously valid scripts could become invalid (or vice versa), creating a minefield of consensus edge cases. Satoshi apparently recognized this and disabled the opcode early in Bitcoin's history.

Why It Is Disabled

OP_VER is classified as a "disabled opcode" — a category that also includes OP_CAT, OP_SUBSTR, OP_LEFT, OP_RIGHT, OP_INVERT, OP_AND, OP_OR, OP_XOR, OP_2MUL, OP_2DIV, OP_MUL, OP_DIV, OP_MOD, OP_LSHIFT, OP_RSHIFT.

// From src/script/interpreter.cpp
// Disabled opcodes check (happens before execution)
if (opcode == OP_CAT || opcode == OP_SUBSTR ||
    opcode == OP_LEFT || opcode == OP_RIGHT ||
    opcode == OP_INVERT || opcode == OP_AND ||
    opcode == OP_OR || opcode == OP_XOR ||
    opcode == OP_2MUL || opcode == OP_2DIV ||
    opcode == OP_MUL || opcode == OP_DIV ||
    opcode == OP_MOD || opcode == OP_LSHIFT ||
    opcode == OP_RSHIFT || opcode == OP_VER)
{
    return set_error(serror, SCRIPT_ERR_DISABLED_OPCODE);
}

The check happens at opcode processing time, but it is applied even to opcodes in branches that fExec (the execution flag) would otherwise skip.

Comparison with OP_RESERVED

OP_RESERVED (0x50):
  - Fails only if executed (i.e., in active branch)
  - Safe in dead branches (OP_FALSE OP_IF OP_RESERVED OP_ENDIF succeeds)
  - Use case: delineating script templates, future upgrades

OP_VER (0x62):
  - Fails unconditionally (in any branch, executed or not)
  - Identical behavior to hard-disabled opcodes
  - Use case: none (purely historical artifact)

Can OP_VER Be Re-Enabled?

Re-enabling OP_VER (or any disabled opcode) would require a hard fork, because it would make previously invalid scripts (those containing OP_VER) potentially valid. This is the opposite of a soft fork. For a disabled opcode to become valid again, all nodes in the network would need to upgrade simultaneously to the new rules — a hard fork by definition.

Given that no useful behavior was ever assigned to OP_VER and that its original intent (version-dependent scripts) is widely considered a bad idea, there is no serious proposal to re-enable it.


☕ Help support TeachMeBitcoin

TeachMeBitcoin is an ad-free, open-source educational repository curated by a passionate team of Bitcoin researchers and educators for public benefit. If you found our articles helpful, please consider supporting our hosting and ongoing content updates with a clean donation:

Ethereum: 0x578417C51783663D8A6A811B3544E1f779D39A85
Bitcoin: bc1q77k9e95rn669kpzyjr8ke9w95zhk7pa5s63qzz
Solana: 4ycT2ayqeMucixj3wS8Ay8Tq9NRDYRPKYbj3UGESyQ4J
Address copied to clipboard!