TeachMeBitcoin

Minimal Push Rules (BIP 62)

From TeachMeBitcoin, the free encyclopedia Reading time: 3 min

7. Minimal Push Rules (BIP 62)

Overview

BIP 62, titled "Dealing with malleability," introduced a comprehensive set of rules to make Bitcoin transactions non-malleable — or at minimum, to eliminate the most common forms of transaction malleability. A central component of BIP 62 is the "minimal push" rule, which mandates that any data push in a script must use the most compact encoding available for the data being pushed.

The Malleability Problem

Before BIP 62, a third party could modify a transaction's scriptSig (and therefore its transaction ID / txid) without invalidating the signatures, because scripts could encode the same data in multiple valid but differently-encoded ways. For example, the integer 1 could be pushed as:

Minimal encoding (OP_1):
0x51  (1 byte)

Non-minimal but valid encoding:
0x01 0x01  (2 bytes: push-1-byte prefix + value 0x01)

Also non-minimal:
0x4c 0x01 0x01  (3 bytes: OP_PUSHDATA1 + length + value)

All three push the same value onto the stack and produce the same script execution result. But they produce different raw bytes in the transaction, yielding different txids. Miners or other relay nodes could substitute one encoding for another, changing the txid without breaking validity.

BIP 62 Minimal Push Rules

BIP 62 specifies a strict mapping from data being pushed to the opcode that must be used:

Rule 1: Empty data must use OP_0
  Data = []           --> must use 0x00 (OP_0)

Rule 2: Data equal to OP_1..OP_16 range must use those opcodes
  Data = [0x01]       --> must use 0x51 (OP_1)
  Data = [0x02]       --> must use 0x52 (OP_2)
  ...
  Data = [0x10]       --> must use 0x60 (OP_16)

Rule 3: Data equal to -1 must use OP_1NEGATE
  Data = [0x81]       --> must use 0x4f (OP_1NEGATE)

Rule 4: Data of 1–75 bytes must use direct push
  len(data) in [1,75] --> opcode = len(data), then data bytes

Rule 5: Data of 76–255 bytes must use OP_PUSHDATA1
  len(data) in [76,255] --> 0x4c <len:1 byte> <data>

Rule 6: Data of 256–65535 bytes must use OP_PUSHDATA2
  len(data) in [256,65535] --> 0x4d <len:2 bytes LE> <data>

Rule 7: Data of 65536+ bytes must use OP_PUSHDATA4
  len(data) >= 65536 --> 0x4e <len:4 bytes LE> <data>

Enforcement Status

BIP 62 was partially deployed. The minimal push rules were adopted into Bitcoin Core's standardness checking (mempool policy) but were never made consensus-critical for scriptSig data pushes via a soft fork. This means:

// From src/script/script.cpp - IsMinimalPush check
bool CheckMinimalPush(const valtype& data, opcodetype opcode) {
    if (data.size() == 0) {
        return opcode == OP_0;
    } else if (data.size() == 1 && data[0] >= 1 && data[0] <= 16) {
        return opcode == OP_1 + (data[0] - 1);
    } else if (data.size() == 1 && data[0] == 0x81) {
        return opcode == OP_1NEGATE;
    } else if (data.size() <= 75) {
        return opcode == data.size();
    } else if (data.size() <= 255) {
        return opcode == OP_PUSHDATA1;
    } else if (data.size() <= 65535) {
        return opcode == OP_PUSHDATA2;
    } else {
        return opcode == OP_PUSHDATA4;
    }
}

Impact on SegWit and Taproot

SegWit (BIP 141) made minimal push a consensus requirement for witness script elements. Taproot (BIP 341) inherits this through the tapscript validation rules. This means that post-SegWit, any witness data using non-minimal pushes is consensus-invalid, not merely non-standard.


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