TeachMeBitcoin

OP_SIZE - Measuring Stack Item Byte Length

From TeachMeBitcoin, the free encyclopedia Reading time: 4 min

7. OP_SIZE — Measuring Stack Item Byte Length

Overview

OP_SIZE is the one member of the string opcode family that was never disabled and remains fully active in Bitcoin Script today. It measures the byte length of the top stack item and pushes that length as an integer — crucially, without consuming or removing the item being measured.

Opcode value: 0x82 Current status: Active and enabled

Behavior

Stack before: [ ... <item> ]
                       ↑ top

OP_SIZE:
  Peeks at top item (does NOT pop it)
  Computes len = byte length of top item
  Pushes len as a CScript integer

Stack after: [ ... <item> <len> ]
  (item remains! len is pushed ON TOP)

Example:
  Stack before: [ 0xDEADBEEF ]   (4 bytes)
  OP_SIZE
  Stack after:  [ 0xDEADBEEF 0x04 ]  (item preserved, length 4 pushed)

Example 2:
  Stack before: [ 0x ]   (empty byte array, length 0)
  OP_SIZE
  Stack after:  [ 0x 0x ]  (item preserved, length 0 as CScript 0 = empty)

The Non-Destructive Property

The non-destructive peek is unusual and deliberate. In most cases, you want to know the size of something AND still do something with it. If OP_SIZE consumed the item, you'd have to duplicate it first every time:

If OP_SIZE were destructive (hypothetical):
  OP_DUP OP_SIZE → would be needed to get size while keeping item
  (wasteful — extra opcode and stack manipulation)

Since OP_SIZE is non-destructive:
  <item> OP_SIZE → leaves both item and its size on stack
  No extra OP_DUP needed

Common Uses

1. Enforcing minimum/maximum data lengths:

Enforce that a provided preimage is exactly 32 bytes:
  scriptPubKey:
    OP_SIZE OP_32 OP_EQUALVERIFY OP_SHA256 <hash> OP_EQUAL

  Execution:

Stack: [ ]

OP_SIZE  → [ <preimage> <len(preimage)> ]
    OP_32    → [ <preimage> <len(preimage)> 0x20 ]  (0x20 = 32 decimal)
    OP_EQUALVERIFY → asserts len == 32, stack: [ <preimage> ]
    OP_SHA256 → [ SHA256(preimage) ]
    <hash>   → [ SHA256(preimage) <hash> ]
    OP_EQUAL → [ 0x01 ]

This pattern is used in Hash Time-Locked Contracts (HTLCs) — the backbone of Lightning Network payment channels. The 32-byte preimage size enforcement prevents certain griefing attacks.

2. Detecting empty vs non-empty items:

Check if top item is non-empty (has at least 1 byte):
  OP_SIZE OP_0 OP_NUMGREATER

  Or check for exactly empty:
  OP_SIZE OP_NOT  (OP_NOT on 0 gives 1, on non-zero gives 0)

3. Variable-length data handling:

Script that accepts EITHER a 20-byte or 32-byte hash (two payment modes):
  OP_SIZE OP_DUP
  OP_20 OP_EQUAL
  IF
    OP_HASH160 <20-byte-hash> OP_EQUAL
  ELSE
    OP_32 OP_EQUALVERIFY OP_SHA256 <32-byte-hash> OP_EQUAL
  ENDIF

  (Conceptual — OP_IF would need numeric truth value from OP_SIZE result)

4. In HTLC scripts (Lightning Network):

The Lightning Network's HTLC output scripts use OP_SIZE explicitly:

OP_SIZE 0x20 OP_EQUALVERIFY OP_HASH160 <payment_hash> OP_EQUALVERIFY ...

The OP_SIZE 0x20 OP_EQUALVERIFY part ensures the preimage provided is exactly 32 bytes, preventing malleability attacks where a shorter but still-hashing-correctly preimage might be substituted.

Size of the Empty Stack Item

A subtle but important behavior:

Empty byte array: 0x (zero bytes)
OP_SIZE on empty → pushes 0x (CScript integer 0 = empty byte array)

So the SIZE of an empty item is 0, represented as the empty byte array.
This is consistent with CScript integer encoding where 0 = 0x (empty).

Stack: [ 0x ]

OP_SIZE → [ 0x 0x ]
  (two empty byte arrays: the item itself, and its size = 0)

Size Limits and Maximums

In standard Bitcoin Script, stack items are limited to 520 bytes. So the maximum value OP_SIZE would ever return in a standard script is 520 (0x0802 in CScript little-endian encoding). In Tapscript, the default limit is still 520 bytes per element, though custom limits may apply in some proposals.

Summary

OP_SIZE is the survivor — the one string-inspection opcode that Satoshi kept when disabling the rest. Its non-destructive nature, combined with its ability to enforce byte-length constraints, makes it invaluable in modern Bitcoin Script. Its most prominent real-world use is in Lightning Network HTLCs, where it guards against preimage length manipulation. It is proof that even without the full string manipulation family, Bitcoin Script retains meaningful data-inspection power.

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