TeachMeBitcoin

OP_CAT - Disabled String Concatenation

From TeachMeBitcoin, the free encyclopedia Reading time: 4 min

4. OP_CAT — Disabled String Concatenation

Overview

OP_CAT (opcode 0x7E) was one of the original opcodes in Satoshi Nakamoto's first release of Bitcoin. Its purpose was simple: concatenate two byte strings from the top of the stack into a single byte string and push the result back. It was disabled in August 2010, but it remains one of the most discussed and debated disabled opcodes in Bitcoin's history — with serious proposals to re-enable it circulating in the community today.

Opcode value: 0x7E Current status: Disabled (causes immediate script failure if encountered)

Original Intended Behavior

Stack before: [ <item_A> <item_B> ]
                               ↑ top

OP_CAT:
  Pops item_B (top)
  Pops item_A
  Concatenates: result = item_A || item_B  (A followed by B)
  Pushes result

Stack after: [ <item_A || item_B> ]

Example:
  item_A = 0xDEAD   (2 bytes)
  item_B = 0xBEEF   (2 bytes)
  Result = 0xDEADBEEF (4 bytes)

The Power of OP_CAT

Despite its simple definition, OP_CAT enables an enormous range of capabilities when combined with other opcodes. Consider what becomes possible:

1. Constructing structured data on-chain:

Example: Building a custom hash preimage inline
  <prefix> <payload> OP_CAT OP_SHA256 <expected_hash> OP_EQUAL
  This allows spending a UTXO by providing a payload such that
  SHA256(prefix || payload) == expected_hash
  Without OP_CAT, prefix and payload must be pre-concatenated off-chain.

2. Schnorr signature introspection (with OP_CAT + OP_CHECKSIG tricks):

A famous trick: using OP_CAT to enforce that r-value of Schnorr sig
equals a specific nonce (signature grinding prevention / covenant-like).

Concept:
  <fixed_r_value> <s_value> OP_CAT → creates a full 64-byte Schnorr sig
  OP_CHECKSIG → verifies it
  This constrains what r-values are valid, creating a form of covenant.

3. Merkle proof verification:

OP_CAT enables on-chain Merkle proof verification:
  Loop (unrolled):
    <leaf_hash> <sibling_hash> OP_CAT OP_SHA256 → <parent_hash>
    <parent_hash> <next_sibling> OP_CAT OP_SHA256 → <grandparent_hash>
    ... continuing up the tree ...
    <root> OP_EQUAL

  This allows Bitcoin script to validate SPV proofs,
  enabling trustless Bitcoin bridges and pegged sidechains.

4. Vault constructions:

With OP_CAT, a vault can enforce spending conditions by constructing
and verifying transaction structure inline:

  <txid_prefix> <output_index> OP_CAT → <outpoint>
  <outpoint> <script_hash> OP_CAT → <partial_tx_data>
  OP_SHA256 <covenant_hash> OP_EQUAL

  This creates primitive covenant behavior — constraining where funds can go.

Why It Was Dangerous (The Memory Attack Vector)

The reason OP_CAT was disabled was a well-known vulnerability: unbounded memory growth.

Without any size limit, an attacker could use OP_CAT in a loop-like structure (via OP_DUP and OP_CAT) to exponentially grow stack items:

Attack script:
  OP_1                  ; Push 0x01 (1 byte)
  OP_DUP OP_CAT         ; Stack: [ 0x0101 ]  (2 bytes)
  OP_DUP OP_CAT         ; Stack: [ 0x01010101 ]  (4 bytes)
  OP_DUP OP_CAT         ; Stack: [ 8 bytes ]
  OP_DUP OP_CAT         ; Stack: [ 16 bytes ]
  OP_DUP OP_CAT         ; Stack: [ 32 bytes ]
  ... (repeat 30 times total) ...
  ; After 30 doublings: 2^30 bytes = ~1 GB on the stack!

This would crash or freeze any node that tried to validate it.
The attack is cheap to construct but astronomically expensive to execute.

With only ~40 opcodes, an attacker could produce gigabytes of stack data, creating a Denial-of-Service attack against the entire network.

The 2010 Disabling

On August 15, 2010, Satoshi Nakamoto pushed a commit that disabled OP_CAT along with several other string and bitwise opcodes. The fix was straightforward: any script containing OP_CAT would immediately fail. The Bitcoin network soft-forked this change in.

Current behavior:
  Encountering 0x7E in a script → script_ERR_DISABLED_OPCODE
  Transaction is immediately invalid

OP_CAT in Tapscript (BIP-347)

A formal proposal to re-enable OP_CAT in Tapscript has been drafted as BIP-347. The proposal includes a critical safeguard: a 520-byte maximum stack element size, enforced at the point of the OP_CAT operation.

Proposed OP_CAT behavior (BIP-347):
  if len(item_A) + len(item_B) > 520:
    FAIL script  ← prevents memory explosion
  else:
    Push item_A || item_B

This 520-byte limit is already the stack item size limit in Bitcoin Script,
so it's a natural and consistent bound.

With this size cap, the exponential doubling attack is stopped after about 9 doublings (2^9 = 512 < 520), making it practically harmless.

Summary

OP_CAT is perhaps the most consequential disabled opcode in Bitcoin. Its re-enablement would unlock covenants, Merkle proof verification, trustless bridges, and sophisticated vault constructions — all with just a single opcode. The debate around its revival is covered in depth in section 10.

☕ 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!