Bitcoin Script ASM Format
Every library prints Bitcoin script in a slightly different readable form, so output from one tool is not accepted by another. This fixes one form so scripts can be moved between tools and languages.
Reference for an AI
Everything an assistant needs to answer questions about BRC-106 accurately, including what it depends on.
Summary
- Why
- Different code libraries produce inconsistent text representations of the same Bitcoin Script, which breaks comparisons and interoperability across tools.
- What
- BRC-106 is a standard that fixes exactly which text name each Bitcoin Script opcode must use when converted to and from its human-readable ASM form.
- How
- A library parses any valid alias of an opcode (such as OP_0 or OP_FALSE) into the same underlying byte, but always outputs the single designated human-readable name (such as OP_FALSE) when converting that byte back to ASM text.
What this lets you do
- Parse any known opcode alias into its correct byte value
- Serialize a script to ASM using one consistent name per opcode
- Compare ASM output from different libraries and expect a byte-for-byte match
- Look up any opcode's canonical ASM name and hex value in a shared table
Written by claude-sonnet-5 from the specification text. Where the two differ, the original is correct.
The specification
Abstract
This proposal introduces a standardised method of dealing with the ASM representation of Bitcoin Script across the ecosystem language libraries (Py-SDK, TS-SDK, Go-SDK, Teranode etc).
Motivation
The purpose of this proposal is to provide a generalised standard in order for deterministic translation of Bitcoin Script to and from ASM for cross-language compatibility.
Currently, different implementations may produce inconsistent ASM representations for the same script. For example, the boolean value false might be rendered as OP_0, OP_FALSE depending on the library used. This lack of standardisation creates interoperability issues when scripts are shared across different tools and platforms.
Specification
- It is important that ASM format scripts operate correctly regardless of where they were produced or processed.
- The Hexadecimal and Binary representations are defined in BRC-14.
- Since ASM format is primarily used for human-readability, op-codes with multiple representations like the boolean pair
[OP_0, OP_1]are to be represented as their english full-name counterpart e.g.[OP_FALSE, OP_TRUE]Example:
Hex: 0x00 0x51
ASM: OP_FALSE OP_TRUE
Not: OP_0 OP_1
- Other discrepancies were found and documented here and rules are set out below to deal with them.
Implementation
- The logic dealing with Bitcoin Script ASM is to be standardised across libraries and languages as described hereunder.
- Op-Codes with several names must be parsed into the correct hex/binary byte despite the chosen ASM format name. Example Input Parsing:
// All of these should parse to 0x00
parseASM("OP_0") // ✓ valid
parseASM("OP_FALSE") // ✓ valid
// Both should output the same hex
parseASM("OP_0") === parseASM("OP_FALSE") // true
- However op-codes with several names must be output into the most human-readable format (e.g.
OP_0will always output asOP_FALSE). Example Output Serialization:
// Input hex, always outputs human-readable form
toASM(0x00) // "OP_FALSE" (not "OP_0")
toASM(0x51) // "OP_TRUE" (not "OP_1")
- Full Op-Code to Hex Table With Statuses
| Index | Word | Hex | Legacy | Chronicles |
|---|---|---|---|---|
| 0 | OP_FALSE | 0x00 | ✅ | ✅ |
| 1-75 | OP_PUSHDATA | 0x01-0x4b | ✅ | ✅ |
| 76 | OP_PUSHDATA1 | 0x4c | ✅ | ✅ |
| 77 | OP_PUSHDATA2 | 0x4d | ✅ | ✅ |
| 78 | OP_PUSHDATA4 | 0x4e | ✅ | ✅ |
| 79 | OP_1NEGATE | 0x4f | ✅ | ✅ |
| 80 | OP_RESERVED | 0x50 | Reserved | Reserved |
| 81 | OP_TRUE | 0x51 | ✅ | ✅ |
| 82 | OP_2 | 0x52 | ✅ | ✅ |
| 83 | OP_3 | 0x53 | ✅ | ✅ |
| 84 | OP_4 | 0x54 | ✅ | ✅ |
| 85 | OP_5 | 0x55 | ✅ | ✅ |
| 86 | OP_6 | 0x56 | ✅ | ✅ |
| 87 | OP_7 | 0x57 | ✅ | ✅ |
| 88 | OP_8 | 0x58 | ✅ | ✅ |
| 89 | OP_9 | 0x59 | ✅ | ✅ |
| 90 | OP_10 | 0x5a | ✅ | ✅ |
| 91 | OP_11 | 0x5b | ✅ | ✅ |
| 92 | OP_12 | 0x5c | ✅ | ✅ |
| 93 | OP_13 | 0x5d | ✅ | ✅ |
| 94 | OP_14 | 0x5e | ✅ | ✅ |
| 95 | OP_15 | 0x5f | ✅ | ✅ |
| 96 | OP_16 | 0x60 | ✅ | ✅ |
| 97 | OP_NOP | 0x61 | ✅ | ✅ |
| 98 | OP_VER | 0x62 | ❌ | ✅ |
| 99 | OP_IF | 0x63 | ✅ | ✅ |
| 100 | OP_NOTIF | 0x64 | ✅ | ✅ |
| 101 | OP_VERIF | 0x65 | ❌ | ✅ |
| 102 | OP_VERNOTIF | 0x66 | ❌ | ✅ |
| 103 | OP_ELSE | 0x67 | ✅ | ✅ |
| 104 | OP_ENDIF | 0x68 | ✅ | ✅ |
| 105 | OP_VERIFY | 0x69 | ✅ | ✅ |
| 106 | OP_RETURN | 0x6a | ✅ | ✅ |
| 107 | OP_TOALTSTACK | 0x6b | ✅ | ✅ |
| 108 | OP_FROMALTSTACK | 0x6c | ✅ | ✅ |
| 109 | OP_2DROP | 0x6d | ✅ | ✅ |
| 110 | OP_2DUP | 0x6e | ✅ | ✅ |
| 111 | OP_3DUP | 0x6f | ✅ | ✅ |
| 112 | OP_2OVER | 0x70 | ✅ | ✅ |
| 113 | OP_2ROT | 0x71 | ✅ | ✅ |
| 114 | OP_2SWAP | 0x72 | ✅ | ✅ |
| 115 | OP_IFDUP | 0x73 | ✅ | ✅ |
| 116 | OP_DEPTH | 0x74 | ✅ | ✅ |
| 117 | OP_DROP | 0x75 | ✅ | ✅ |
| 118 | OP_DUP | 0x76 | ✅ | ✅ |
| 119 | OP_NIP | 0x77 | ✅ | ✅ |
| 120 | OP_OVER | 0x78 | ✅ | ✅ |
| 121 | OP_PICK | 0x79 | ✅ | ✅ |
| 122 | OP_ROLL | 0x7a | ✅ | ✅ |
| 123 | OP_ROT | 0x7b | ✅ | ✅ |
| 124 | OP_SWAP | 0x7c | ✅ | ✅ |
| 125 | OP_TUCK | 0x7d | ✅ | ✅ |
| 126 | OP_CAT | 0x7e | ✅ | ✅ |
| 127 | OP_SPLIT | 0x7f | ✅ | ✅ |
| 128 | OP_NUM2BIN | 0x80 | ✅ | ✅ |
| 129 | OP_BIN2NUM | 0x81 | ✅ | ✅ |
| 130 | OP_SIZE | 0x82 | ✅ | ✅ |
| 131 | OP_INVERT | 0x83 | ✅ | ✅ |
| 132 | OP_AND | 0x84 | ✅ | ✅ |
| 133 | OP_OR | 0x85 | ✅ | ✅ |
| 134 | OP_XOR | 0x86 | ✅ | ✅ |
| 135 | OP_EQUAL | 0x87 | ✅ | ✅ |
| 136 | OP_EQUALVERIFY | 0x88 | ✅ | ✅ |
| 137 | OP_RESERVED1 | 0x89 | Reserved | Reserved |
| 138 | OP_RESERVED2 | 0x8a | Reserved | Reserved |
| 139 | OP_1ADD | 0x8b | ✅ | ✅ |
| 140 | OP_1SUB | 0x8c | ✅ | ✅ |
| 141 | OP_2MUL | 0x8d | ❌ | ✅ |
| 142 | OP_2DIV | 0x8e | ❌ | ✅ |
| 143 | OP_NEGATE | 0x8f | ✅ | ✅ |
| 144 | OP_ABS | 0x90 | ✅ | ✅ |
| 145 | OP_NOT | 0x91 | ✅ | ✅ |
| 146 | OP_0NOTEQUAL | 0x92 | ✅ | ✅ |
| 147 | OP_ADD | 0x93 | ✅ | ✅ |
| 148 | OP_SUB | 0x94 | ✅ | ✅ |
| 149 | OP_MUL | 0x95 | ✅ | ✅ |
| 150 | OP_DIV | 0x96 | ✅ | ✅ |
| 151 | OP_MOD | 0x97 | ✅ | ✅ |
| 152 | OP_LSHIFT | 0x98 | ✅ | ✅ |
| 153 | OP_RSHIFT | 0x99 | ✅ | ✅ |
| 154 | OP_BOOLAND | 0x9a | ✅ | ✅ |
| 155 | OP_BOOLOR | 0x9b | ✅ | ✅ |
| 156 | OP_NUMEQUAL | 0x9c | ✅ | ✅ |
| 157 | OP_NUMEQUALVERIFY | 0x9d | ✅ | ✅ |
| 158 | OP_NUMNOTEQUAL | 0x9e | ✅ | ✅ |
| 159 | OP_LESSTHAN | 0x9f | ✅ | ✅ |
| 160 | OP_GREATERTHAN | 0xa0 | ✅ | ✅ |
| 161 | OP_LESSTHANOREQUAL | 0xa1 | ✅ | ✅ |
| 162 | OP_GREATERTHANOREQUAL | 0xa2 | ✅ | ✅ |
| 163 | OP_MIN | 0xa3 | ✅ | ✅ |
| 164 | OP_MAX | 0xa4 | ✅ | ✅ |
| 165 | OP_WITHIN | 0xa5 | ✅ | ✅ |
| 166 | OP_RIPEMD160 | 0xa6 | ✅ | ✅ |
| 167 | OP_SHA1 | 0xa7 | ✅ | ✅ |
| 168 | OP_SHA256 | 0xa8 | ✅ | ✅ |
| 169 | OP_HASH160 | 0xa9 | ✅ | ✅ |
| 170 | OP_HASH256 | 0xaa | ✅ | ✅ |
| 171 | OP_CODESEPARATOR | 0xab | ✅ | ✅ |
| 172 | OP_CHECKSIG | 0xac | ✅ | ✅ |
| 173 | OP_CHECKSIGVERIFY | 0xad | ✅ | ✅ |
| 174 | OP_CHECKMULTISIG | 0xae | ✅ | ✅ |
| 175 | OP_CHECKMULTISIGVERIFY | 0xaf | ✅ | ✅ |
| 176 | OP_NOP1 | 0xb0 | ✅ | ✅ |
| 177 | OP_NOP2 | 0xb1 | ✅ | ✅ |
| 178 | OP_NOP3 | 0xb2 | ✅ | ✅ |
| 179 | OP_SUBSTR | 0xb3 | ❌ | ✅ |
| 180 | OP_LEFT | 0xb4 | ❌ | ✅ |
| 181 | OP_RIGHT | 0xb5 | ❌ | ✅ |
| 182 | OP_NOP4 | 0xb6 | ✅ | ✅ |
| 183 | OP_NOP5 | 0xb7 | ✅ | ✅ |
| 184 | OP_NOP6 | 0xb8 | ✅ | ✅ |
| 185 | OP_NOP7 | 0xb9 | ✅ | ✅ |
| 186 | OP_NOP8 | 0xba | ✅ | ✅ |
| 187 | OP_NOP9 | 0xbb | ✅ | ✅ |
| 188 | OP_NOP10 | 0xbc | ✅ | ✅ |
| 253 | OP_PUBKEYHASH | 0xfd | Pseudo | Pseudo |
| 254 | OP_PUBKEY | 0xfe | Pseudo | Pseudo |
| 255 | OP_INVALIDOPCODE | 0xff | Invalid | Invalid |
References
- <a name="footnote-1">BRC-14</a>: Bitcoin Script Binary and Hex Formats - Ty Everett (ty@projectbabbage.com)