Python pseudocode for script atom parser
11. Push Data Encoding in Raw Hex
Overview
Bitcoin scripts are serialized as raw byte strings. When reading, debugging, or constructing scripts manually, it is essential to understand how to interpret and write push data operations in raw hexadecimal notation. This section covers the complete set of encoding patterns for push data in hex and provides worked examples for real-world script types.
Hex Encoding Rules Summary
Push empty (0 bytes):
Hex: 00
Meaning: OP_0, pushes []
Push 1–75 bytes (direct push):
Hex: <length_hex> <data_hex>
Example (1 byte 0xFF): 01 ff
Example (3 bytes): 03 aa bb cc
Example (20-byte hash): 14 <40 hex chars>
Example (33-byte pubkey): 21 <66 hex chars>
Push 76–255 bytes (OP_PUSHDATA1):
Hex: 4c <length_hex:2 chars> <data_hex>
Example (100 bytes): 4c 64 <200 hex chars>
Example (200 bytes): 4c c8 <400 hex chars>
Push 256–65535 bytes (OP_PUSHDATA2):
Hex: 4d <length_hex:4 chars little-endian> <data_hex>
Example (256 bytes = 0x0100 LE = 0001): 4d 00 01 <512 hex chars>
Push special values:
OP_1NEGATE: 4f (pushes -1 = [0x81])
OP_1: 51 (pushes 1 = [0x01])
OP_2: 52
...
OP_16: 60
Worked Example: P2PKH ScriptPubKey
P2PKH scriptPubKey hex:
76 a9 14 89abcdefabbaabbaabbaabbaabbaabbaabbaabba 88 ac
Parsed:
76 --> OP_DUP
a9 --> OP_HASH160
14 --> push 20 bytes (direct push, length=0x14=20)
89ab...abba --> the 20-byte hash (pubkey hash)
88 --> OP_EQUALVERIFY
ac --> OP_CHECKSIG
Worked Example: P2WPKH ScriptPubKey
P2WPKH scriptPubKey hex:
00 14 89abcdefabbaabbaabbaabbaabbaabbaabbaabba
Parsed:
00 --> OP_0 (SegWit version 0)
14 --> push 20 bytes (direct push)
89ab...abba --> the 20-byte witness program (pubkey hash)
Worked Example: P2WSH ScriptPubKey
P2WSH scriptPubKey hex:
00 20 <64-hex-char SHA256 hash>
Parsed:
00 --> OP_0 (SegWit version 0)
20 --> push 32 bytes (direct push, 0x20=32)
<32 bytes> --> SHA256 of the witness script
Worked Example: P2TR (Taproot) ScriptPubKey
P2TR scriptPubKey hex:
51 20 <64-hex-char x-only pubkey>
Parsed:
51 --> OP_1 (SegWit version 1 = Taproot)
20 --> push 32 bytes
<32 bytes> --> x-only tweaked public key
Worked Example: Multisig Locking Script
2-of-3 P2MS scriptPubKey hex:
52 OP_2
21 <33-byte-pubkey1> push compressed pubkey 1
21 <33-byte-pubkey2> push compressed pubkey 2
21 <33-byte-pubkey3> push compressed pubkey 3
53 OP_3
ae OP_CHECKMULTISIG
Reading Raw Transaction Scripts
To decode a script from a raw transaction hex, isolate the script bytes and parse atom by atom. Each atom begins with the current byte; if that byte is in [0x01, 0x4b], the atom is a direct push and you consume that many following bytes as data.
# Python pseudocode for script atom parser
def parse_script(hex_str):
data = bytes.fromhex(hex_str)
pos = 0
while pos < len(data):
op = data[pos]; pos += 1
if op == 0x00:
yield ("OP_0", b"")
elif 0x01 <= op <= 0x4b:
yield ("PUSH", data[pos:pos+op]); pos += op
elif op == 0x4c:
n = data[pos]; pos += 1
yield ("PUSHDATA1", data[pos:pos+n]); pos += n
elif op == 0x4d:
n = int.from_bytes(data[pos:pos+2], 'little'); pos += 2
yield ("PUSHDATA2", data[pos:pos+n]); pos += n
elif op == 0x4e:
n = int.from_bytes(data[pos:pos+4], 'little'); pos += 4
yield ("PUSHDATA4", data[pos:pos+n]); pos += n
else:
yield ("OPCODE", op)
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: